<< All versions
Skill v1.0.1
currentAutomated scan100/100secondsky/claude-skills/bun-websocket-server
1 files
──Details
PublishedMay 24, 2026 at 03:31 PM
Content Hashsha256:f1f0c627ecd3759b...
Git SHA5e92b7170451
Bump Typepatch
──Files
Files (1 file, 7.1 KB)
SKILL.md7.1 KBactive
SKILL.md · 358 lines · 7.1 KB
version: "1.0.1" name: bun-websocket-server description: This skill should be used when the user asks about "WebSocket in Bun", "real-time communication", "Bun.serve websocket", "ws server", "socket connections", "pub/sub", "broadcasting messages", "WebSocket upgrade", or building real-time applications with Bun. metadata: version: "1.0.0" license: MIT
Bun WebSocket Server
Bun has built-in WebSocket support integrated with Bun.serve().
Quick Start
typescript
const server = Bun.serve({fetch(req, server) {// Upgrade to WebSocketif (server.upgrade(req)) {return; // Upgraded successfully}return new Response("Not a WebSocket request", { status: 400 });},websocket: {open(ws) {console.log("Client connected");},message(ws, message) {console.log("Received:", message);ws.send(`Echo: ${message}`);},close(ws) {console.log("Client disconnected");},},});console.log(`WebSocket server running on ws://localhost:${server.port}`);
WebSocket Handlers
typescript
Bun.serve({fetch(req, server) {server.upgrade(req);},websocket: {// Client connectedopen(ws) {console.log("New connection");},// Message receivedmessage(ws, message) {// message is string | Bufferif (typeof message === "string") {console.log("Text:", message);} else {console.log("Binary:", message);}},// Connection closedclose(ws, code, reason) {console.log(`Closed: ${code} - ${reason}`);},// Drain event (buffer flushed)drain(ws) {console.log("Buffer drained");},// Ping receivedping(ws, data) {// Pong sent automatically},// Pong receivedpong(ws, data) {console.log("Pong received");},},});
Sending Messages
typescript
websocket: {message(ws, message) {// Send textws.send("Hello");// Send JSONws.send(JSON.stringify({ type: "greeting", data: "Hello" }));// Send binaryws.send(new Uint8Array([1, 2, 3]));ws.send(Buffer.from("binary data"));// Send with compressionws.send("compressed message", true);// Check if buffer is fullconst bufferedAmount = ws.send("data");if (bufferedAmount > 1024 * 1024) {console.log("Buffer getting full");}},}
Attaching Data to Connections
typescript
interface UserData {id: string;name: string;joinedAt: Date;}Bun.serve<UserData>({fetch(req, server) {const url = new URL(req.url);const userId = url.searchParams.get("userId");// Attach data during upgradeserver.upgrade(req, {data: {id: userId,name: "User " + userId,joinedAt: new Date(),},});},websocket: {open(ws) {// Access attached dataconsole.log(`${ws.data.name} connected`);},message(ws, message) {console.log(`${ws.data.name}: ${message}`);},},});
Pub/Sub (Topics)
typescript
Bun.serve({fetch(req, server) {const url = new URL(req.url);const room = url.searchParams.get("room") || "general";server.upgrade(req, {data: { room },});},websocket: {open(ws) {// Subscribe to a topicws.subscribe(ws.data.room);// Publish to topic (excludes sender)ws.publish(ws.data.room, `User joined ${ws.data.room}`);},message(ws, message) {// Broadcast to all in room (excludes sender)ws.publish(ws.data.room, message);},close(ws) {// Unsubscribe (automatic on close)ws.unsubscribe(ws.data.room);ws.publish(ws.data.room, "User left");},},});
Broadcasting to All Clients
typescript
Bun.serve({fetch(req, server) {server.upgrade(req);},websocket: {open(ws) {// Subscribe to global topicws.subscribe("global");},message(ws, message) {// Broadcast to ALL clients including senderserver.publish("global", message);},},});
Server-Level Publish
typescript
const server = Bun.serve({fetch(req, server) {const url = new URL(req.url);// HTTP endpoint to publishif (url.pathname === "/broadcast") {const message = url.searchParams.get("msg");server.publish("global", message);return new Response("Broadcasted");}server.upgrade(req);},websocket: {open(ws) {ws.subscribe("global");},},});// Can also publish from outside fetchsetInterval(() => {server.publish("global", `Server time: ${new Date().toISOString()}`);}, 5000);
WebSocket Options
typescript
Bun.serve({websocket: {// Max message size (default 16MB)maxPayloadLength: 1024 * 1024, // 1MB// Idle timeout in seconds (default 120)idleTimeout: 60,// Backpressure limitbackpressureLimit: 1024 * 1024,// Enable compressionperMessageDeflate: true,// Or with optionsperMessageDeflate: {compress: "shared",decompress: "shared",},// Send/receive pingssendPings: true,// Handlersopen(ws) {},message(ws, message) {},close(ws) {},},});
Client-Side Connection
javascript
// Browserconst ws = new WebSocket("ws://localhost:3000");ws.onopen = () => {ws.send("Hello Server!");};ws.onmessage = (event) => {console.log("Received:", event.data);};ws.onclose = () => {console.log("Disconnected");};
Authentication
typescript
Bun.serve({fetch(req, server) {// Verify auth before upgradeconst token = req.headers.get("Authorization");if (!verifyToken(token)) {return new Response("Unauthorized", { status: 401 });}const user = decodeToken(token);server.upgrade(req, {data: { userId: user.id },});},websocket: {open(ws) {console.log(`Authenticated user ${ws.data.userId} connected`);},},});
Common Errors
| Error | Cause | Fix | |
|---|---|---|---|
Upgrade failed | Invalid request | Check upgrade headers | |
Connection closed | Client disconnect | Handle in close handler | |
Message too large | Exceeds maxPayloadLength | Increase limit or chunk data | |
Backpressure | Slow client | Check buffer, wait for drain |
Common Patterns
Chat Room
typescript
Bun.serve({fetch(req, server) {const url = new URL(req.url);const username = url.searchParams.get("user") || "Anonymous";server.upgrade(req, {data: { username },});},websocket: {open(ws) {ws.subscribe("chat");ws.publish("chat", `${ws.data.username} joined`);},message(ws, message) {ws.publish("chat", `${ws.data.username}: ${message}`);},close(ws) {ws.publish("chat", `${ws.data.username} left`);},},});
When to Load References
Load references/compression.md when:
- perMessageDeflate configuration
- Compression tuning
- Binary message handling
Load references/scaling.md when:
- Multiple server instances
- Redis pub/sub integration
- Horizontal scaling