No reconnection logic: Connections drop permanently, causing 35% user disengagement after single drop. Anti-pattern: ws.onclose = () => {}; (no reconnect). Fix: Exponential backoff with jitter - delay = Math.min(30000, 1000 * 2^attempt) + random(1000). Prevents reconnection storms, adds randomization to avoid thundering herd. Critical for production reliability. Libraries: Socket.IO has built-in reconnection, ws library requires manual implementation.
WebSocket Pitfalls Antipatterns FAQ & Answers
7 expert WebSocket Pitfalls Antipatterns answers researched from official documentation. Every answer cites authoritative sources you can verify.
unknown
7 questionsSecurity pitfalls: (1) Insecure connections (ws:// in production exposes to MITM attacks, token theft) - Fix: Always use wss:// with TLS encryption, (2) No authentication (accepting unauthenticated connections vulnerable to hijacking) - Fix: Validate JWT in Sec-WebSocket-Protocol header or httpOnly cookie during handshake, (3) Not validating Origin header (CSRF vulnerability, attackers open WebSocket from malicious domain using victim's cookies) - Fix: Check Origin against allowlist during handshake, reject unauthorized with 403.
No rate limiting: DoS vulnerability - one client floods with messages consuming all resources. Fix: Token bucket algorithm per-IP (10-100 msg/sec) and per-user (50-200 msg/sec). Prevents resource exhaustion from malicious or buggy clients. Monitor metrics: messages/sec per connection, reject or throttle when exceeding limits. Essential for production-grade WebSocket servers.
Ignoring backpressure: Unbounded buffering causes memory exhaustion and OOM crashes. Anti-pattern: for(let i=0; i<1000000; i++) ws.send(data); Fix: Monitor ws.bufferedAmount, pause when exceeds threshold (64KB), implement flow control signals. Unbounded TCP send buffers with slow clients: thousands of slow clients cause server memory spiraling into gigabytes as OS TCP buffers accumulate data. Fix: Detect slow clients, implement write timeouts, close lagging connections. Critical for production stability under load.
No heartbeat mechanism: Can't detect broken connections (TCP keepalive operates at 2-hour intervals, too slow). Fix: Ping/pong every 20-30s, close on repeated missed pongs. Heartbeats detect half-open connections (client disconnected but server doesn't know). Without heartbeats: zombie connections accumulate, wasting resources. Essential for production deployments. Sending large messages: blocks event loop in single-threaded Node.js. Fix: Chunk messages >1MB, use binary frames.
Stateful logic without cleanup: Memory leaks accumulate over time. Anti-pattern: users[userId] = ws; without removing on disconnect. Fix: Unsubscribe event listeners and remove state in ws.onclose handler. Not handling errors: Unhandled exceptions crash server or leave zombie connections. Fix: Wrap handlers in try/catch, attach ws.onerror event listeners. No message validation: SQL/code injection attacks via malformed payloads. Anti-pattern: db.query(message.sql). Fix: Validate JSON schema, sanitize inputs, use parameterized queries.
nginx default 60s read timeout: Idle WebSocket connections disconnect without data transfer. Fix: Add proxy_read_timeout 3600s; proxy_send_timeout 3600s; in nginx location block. Synchronous blocking operations: Event loop starvation under load prevents other connections from being processed. Fix: Use async/await, offload heavy work to worker threads. Broadcasting sensitive admin data to all users: Confidential info (stock levels, promo codes, admin alerts) visible to regular clients. Fix: Validate user permissions before broadcasting, route sensitive messages to specific authenticated users only. Best practices: use battle-tested libraries (ws, Socket.IO, uWebSockets.js), monitor metrics, load test with Artillery/k6.