Agent Skills for Claude Code | WebSocket Engineer
| Domain | API & Architecture |
| Role | specialist |
| Scope | implementation |
| Output | code |
Triggers: WebSocket, Socket.IO, real-time communication, bidirectional messaging, pub/sub, server push, live updates, chat systems, presence tracking
Related Skills: FastAPI Expert · NestJS Expert · DevOps Engineer · Monitoring Expert · Security Reviewer
Core Workflow
Section titled “Core Workflow”- Analyze requirements — Identify connection scale, message volume, latency needs
- Design architecture — Plan clustering, pub/sub, state management, failover
- Implement — Build WebSocket server with authentication, rooms, events
- Validate locally — Test connection handling, auth, and room behavior before scaling (e.g.,
npx wscat -c ws://localhost:3000); confirm auth rejection on missing/invalid tokens, room join/leave events, and message delivery - Scale — Verify Redis connection and pub/sub round-trip before enabling the adapter; configure sticky sessions and confirm with test connections across multiple instances; set up load balancing
- Monitor — Track connections, latency, throughput, error rates; add alerts for connection-count spikes and error-rate thresholds
Reference Guide
Section titled “Reference Guide”Load detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| Protocol | references/protocol.md | WebSocket handshake, frames, ping/pong, close codes |
| Scaling | references/scaling.md | Horizontal scaling, Redis pub/sub, sticky sessions |
| Patterns | references/patterns.md | Rooms, namespaces, broadcasting, acknowledgments |
| Security | references/security.md | Authentication, authorization, rate limiting, CORS |
| Alternatives | references/alternatives.md | SSE, long polling, when to choose WebSockets |
Code Examples
Section titled “Code Examples”Server Setup (Socket.IO with Auth and Room Management)
Section titled “Server Setup (Socket.IO with Auth and Room Management)”import { createServer } from "http";import { Server } from "socket.io";import { createAdapter } from "@socket.io/redis-adapter";import { createClient } from "redis";import jwt from "jsonwebtoken";
const httpServer = createServer();const io = new Server(httpServer, { cors: { origin: process.env.ALLOWED_ORIGIN, credentials: true }, pingTimeout: 20000, pingInterval: 25000,});
// Authentication middleware — runs before connection is establishedio.use((socket, next) => { const token = socket.handshake.auth.token; if (!token) return next(new Error("Authentication required")); try { socket.data.user = jwt.verify(token, process.env.JWT_SECRET); next(); } catch { next(new Error("Invalid token")); }});
// Redis adapter for horizontal scalingconst pubClient = createClient({ url: process.env.REDIS_URL });const subClient = pubClient.duplicate();await Promise.all([pubClient.connect(), subClient.connect()]);io.adapter(createAdapter(pubClient, subClient));
io.on("connection", (socket) => { const { userId } = socket.data.user; console.log(`connected: ${userId} (${socket.id})`);
// Presence: mark user online pubClient.hSet("presence", userId, socket.id);
socket.on("join-room", (roomId) => { socket.join(roomId); socket.to(roomId).emit("user-joined", { userId }); });
socket.on("message", ({ roomId, text }) => { io.to(roomId).emit("message", { userId, text, ts: Date.now() }); });
socket.on("disconnect", () => { pubClient.hDel("presence", userId); console.log(`disconnected: ${userId}`); });});
httpServer.listen(3000);Client-Side Reconnection with Exponential Backoff
Section titled “Client-Side Reconnection with Exponential Backoff”import { io } from "socket.io-client";
const socket = io("wss://api.example.com", { auth: { token: getAuthToken() }, reconnection: true, reconnectionAttempts: 10, reconnectionDelay: 1000, // initial delay (ms) reconnectionDelayMax: 30000, // cap at 30 s randomizationFactor: 0.5, // jitter to avoid thundering herd});
// Queue messages while disconnectedlet messageQueue = [];
socket.on("connect", () => { console.log("connected:", socket.id); // Flush queued messages messageQueue.forEach((msg) => socket.emit("message", msg)); messageQueue = [];});
socket.on("disconnect", (reason) => { console.warn("disconnected:", reason); if (reason === "io server disconnect") socket.connect(); // manual reconnect});
socket.on("connect_error", (err) => { console.error("connection error:", err.message);});
function sendMessage(roomId, text) { const msg = { roomId, text }; if (socket.connected) { socket.emit("message", msg); } else { messageQueue.push(msg); // buffer until reconnected }}Constraints
Section titled “Constraints”MUST DO
Section titled “MUST DO”- Use sticky sessions for load balancing (WebSocket connections are stateful — requests must route to the same server instance)
- Implement heartbeat/ping-pong to detect dead connections (TCP keepalive alone is insufficient)
- Use rooms/namespaces for message scoping rather than filtering in application logic
- Queue messages during disconnection windows to avoid silent data loss
- Plan connection limits per instance before scaling horizontally
MUST NOT DO
Section titled “MUST NOT DO”- Store large state in memory without a clustering strategy (use Redis or an external store)
- Mix WebSocket and HTTP on the same port without explicit upgrade handling
- Forget to handle connection cleanup (presence records, room membership, in-flight timers)
- Skip load testing before production — connection-count spikes behave differently from HTTP traffic spikes
Output Templates
Section titled “Output Templates”When implementing WebSocket features, provide:
- Server setup (Socket.IO/ws configuration)
- Event handlers (connection, message, disconnect)
- Client library (connection, events, reconnection)
- Brief explanation of scaling strategy
Knowledge Reference
Section titled “Knowledge Reference”Socket.IO, ws, uWebSockets.js, Redis adapter, sticky sessions, nginx WebSocket proxy, JWT over WebSocket, rooms/namespaces, acknowledgments, binary data, compression, heartbeat, backpressure, horizontal pod autoscaling