Skip to content
Guide

Scaling WebSocket Connections: A Practical Guide

Scaling WebSocket connections from a few hundred to hundreds of thousands is a different problem from scaling HTTP. Here is how to architect for it — and how managed platforms handle it for you.

Why WebSocket scaling is different

HTTP requests are short-lived — a request comes in, gets served, the connection closes. WebSockets are long-lived — a connection stays open for the duration of a user's session. This means a server with 100 HTTP requests per second might handle 10,000 concurrent WebSocket connections. Memory and file descriptors, not request throughput, become the bottleneck. Each open WebSocket holds connection state in memory.

Single-server limits

A single Node.js process typically handles 10,000–50,000 concurrent WebSocket connections depending on message frequency, payload size, and what work happens per message. Beyond that, you hit limits: memory (each connection + its state), CPU (parsing/routing messages), and file descriptor limits (OS-level). A well-tuned server with uvloop and minimal per-message work can push to 100K+ — openbnet's chat server handles 100K+ concurrent connections per server with <100ms latency.

  • Memory: ~10KB per connection base + message buffers
  • File descriptors: raise ulimit -n (default 1024 on Linux)
  • CPU: JSON parse + route per message becomes the bottleneck
  • Heartbeat: ping/pong every 30s to detect dead connections

Scaling to multiple servers

When one server is not enough, you add more — but now you have a new problem: User A is connected to Server 1, User B is connected to Server 2. If A sends a message to B's room, Server 1 needs to get it to Server 2. The standard solution is a Redis Pub/Sub adapter: each server subscribes to channel updates on Redis. When Server 1 receives a message for room X, it publishes to Redis; Server 2 (which has User B) receives it from Redis and delivers it to B. This is exactly how openbnet syncs across servers.

// Simplified Redis adapter pattern
const redis = require('redis');
const sub = redis.createClient(); // subscriber
const pub = redis.duplicate();    // publisher

// On incoming WebSocket message
ws.on('message', (data) => {
  const msg = JSON.parse(data);
  // Publish to the room's Redis channel
  pub.publish(`room:${msg.roomId}`, JSON.stringify(msg));
});

// Subscribe to rooms this server has connections for
sub.subscribe(`room:${roomId}`);
sub.on('message', (channel, message) => {
  // Forward to local WebSocket connections in this room
  localClients.forEach(c => c.send(message));
});

Load balancing WebSockets

WebSocket load balancing requires sticky sessions or, better, a layer-7 load balancer that upgrades the connection. Nginx, HAProxy, and cloud LBs all support WebSocket proxying. The key: once the WebSocket upgrade happens, the load balancer keeps the TCP connection pinned to one backend — you cannot round-robin individual messages.

For horizontal scaling, add servers behind a load balancer, each running the WebSocket server + Redis adapter. The load balancer distributes new connections; Redis syncs messages across servers. This is the architecture openbnet uses — you do not manage any of it.

Managed platform vs self-hosted

Self-hosting gives you control but means owning: connection management, Redis adapter setup, horizontal scaling, dead-connection cleanup, message persistence, backpressure, and monitoring. A managed platform (openbnet, PubNub, Pusher) handles all of this. For most teams, the managed route is dramatically lower total cost — the engineering hours saved outweigh the subscription fee. openbnet handles 100K+ connections per server, Redis sync, persistence, and AI moderation, starting free.

All guides · Explore openbnet APIs · Developer quickstarts

About openbnet

openbnet is the real-time communication infrastructure company founded by Brian. It builds the openbnet platform — six production-ready APIs for voice, video, chat, live streaming, signaling, and AI content moderation — plus solutions on that platform: Ocodey, the CLI coding agent, and Spaces, managed communities. One openbnet account signs you in to every solution.

Website: openbnet.com · GitHub: github.com/openbnet · X: @openbnet