websocket-builder
$
npx mdskill add TerminalSkills/skills/websocket-builderDeploy production-ready WebSocket servers for real-time features.
- Handles authentication, room management, and connection lifecycles.
- Integrates Redis pub/sub for horizontal scaling and data persistence.
- Uses mature libraries like ws, websockets, or gorilla/websocket.
- Delivers ready-to-use server code with heartbeat and rate limits.
SKILL.md
.github/skills/websocket-builderView on GitHub ↗
---
name: websocket-builder
description: >-
When the user wants to build real-time features using WebSockets. Use when the
user mentions "WebSocket," "real-time," "live updates," "socket," "ws," "push
notifications," "live chat," "streaming data," or "bidirectional communication."
Covers server setup, room management, authentication, reconnection handling,
and scaling with Redis pub/sub. For data persistence, see realtime-database.
license: Apache-2.0
compatibility: "Node.js 18+, Python 3.9+, or Go 1.21+"
metadata:
author: terminal-skills
version: "1.0.0"
category: development
tags: ["websocket", "real-time", "backend", "chat"]
---
# WebSocket Builder
## Overview
Builds production-ready WebSocket servers for real-time features — chat, live dashboards, collaborative editing, notifications. Handles the hard parts: authentication during handshake, room/channel management, connection lifecycle, automatic reconnection, message ordering, and horizontal scaling via Redis pub/sub.
## Instructions
### 1. Server Setup
When setting up a WebSocket server:
- Attach to existing HTTP server (share the port)
- Use a mature library: `ws` for Node.js, `websockets` for Python, `gorilla/websocket` for Go
- Implement ping/pong heartbeats (30s interval, 90s timeout)
- Set max message size to prevent abuse (default: 64KB)
- Add connection limits per user (default: 5 concurrent connections)
### 2. Authentication
Authenticate during the WebSocket handshake, not after:
```
1. Client connects with token in query string: ws://host/ws?token=<jwt>
2. Server validates JWT before upgrading the connection
3. If invalid → reject with 401 before upgrade completes
4. Attach user context to the socket object for later use
```
Do NOT accept auth via a post-connection message — the connection is already open and resources allocated.
### 3. Room/Channel Management
```
RoomManager:
join(socketId, roomId) — Add socket to room, notify members
leave(socketId, roomId) — Remove socket, notify members
broadcast(roomId, event, data, excludeSocketId?) — Send to all in room
getMembers(roomId) — List connected user IDs
getUserRooms(socketId) — List rooms for a socket
On connect: auto-join user's channel rooms from database
On disconnect: leave all rooms, broadcast presence update
```
### 4. Event Routing
Use a message format with event types:
```json
{ "event": "message.send", "data": { "channelId": "ch_1", "content": "Hello" }, "id": "client-uuid" }
```
Route events to handlers:
```
eventHandlers = {
"message.send": handleMessageSend,
"message.edit": handleMessageEdit,
"typing.start": handleTypingStart,
"presence.heartbeat": handleHeartbeat
}
```
Always include a client-generated `id` for idempotency and acknowledgment.
### 5. Scaling with Redis Pub/Sub
For multi-server deployments:
```
1. Each server subscribes to Redis channels matching room IDs
2. On broadcast: publish to Redis channel instead of local-only broadcast
3. Each server receives the publish and forwards to local sockets in that room
4. Use Redis adapter (e.g., @socket.io/redis-adapter or custom with ioredis)
```
### 6. Reconnection Protocol
```
Client-side:
1. On disconnect: attempt reconnect with exponential backoff (1s, 2s, 4s, max 30s)
2. On reconnect: send last_event_id to server
3. Server replays missed events since that ID
4. Client merges with local state, deduplicating by event ID
Server-side:
1. Keep recent events in Redis sorted set (TTL: 1 hour)
2. On reconnect with last_event_id: return all events after that ID
3. If ID is too old (beyond retention): send full state refresh
```
## Examples
### Example 1: Chat WebSocket Server (Node.js)
**Prompt**: "Set up a WebSocket server for my Express app with rooms and JWT auth"
**Output**: Server with authenticated connections, room manager, event routing, ping/pong heartbeats, and reconnection support. Files: `ws/server.ts`, `ws/rooms.ts`, `ws/handlers/`, `ws/middleware/auth.ts`.
### Example 2: Live Dashboard (Python)
**Prompt**: "I need real-time updates for a monitoring dashboard. FastAPI backend, 500 concurrent viewers."
**Output**: WebSocket endpoint with broadcast-only channels (viewers don't send), Redis pub/sub for horizontal scaling, connection pooling, and automatic cleanup. Files: `realtime/server.py`, `realtime/broadcaster.py`, `realtime/redis_pubsub.py`.
## Guidelines
- **Always authenticate at handshake** — never after connection is open
- **Use binary frames** for large payloads (images, files) — text frames for JSON
- **Implement backpressure** — if a client can't keep up, buffer then disconnect
- **Log connection lifecycle** — connect, disconnect, error, room join/leave (debugging is hard without this)
- **Test with connection drops** — kill connections mid-message to verify recovery
- **Set idle timeouts** — disconnect clients that stop sending heartbeats
- **Never trust client input** — validate every message against expected schema
More from TerminalSkills/skills