How do you scale WebSocket connections across multiple servers?
How to scale WebSockets horizontally: sticky sessions, a Redis/Kafka pub/sub backplane, shared presence, and graceful reconnection across many servers.
Expected Interview Answer
You scale WebSockets horizontally by putting many stateful socket servers behind a load balancer with sticky sessions, and connecting them through a shared pub/sub backplane (like Redis, Kafka, or NATS) so a message published on one server reaches clients connected to any other server.
Because a WebSocket is a long-lived stateful connection, the load balancer must use sticky routing (or operate at L4) so a client stays on the server that holds its socket. Since users for the same room land on different servers, no single node has all the sockets, so servers exchange messages over a pub/sub backplane and each fans out to its own local clients. You track presence and room membership in a shared store, add more nodes as connection counts grow, and design for reconnects because sockets drop constantly.
- Adds capacity by running more socket nodes behind one endpoint
- A pub/sub backplane lets any server broadcast to all clients
- Sticky sessions keep a client pinned to its stateful server
- Shared presence store gives a global view of who is online
- Graceful reconnection and draining survive node restarts
AI Mentor Explanation
Imagine a world tournament played in many stadiums at once, each with its own local commentator serving the crowd in that ground. When a wicket falls anywhere, the news goes to a central press wire, and every stadium's commentator relays it to their local audience. The stadiums are socket servers, the fans are clients pinned to their ground, and the press wire is the pub/sub backplane that keeps every crowd in sync.
Step-by-Step Explanation
Step 1
Front with a load balancer
Place all socket nodes behind one L4 or sticky L7 load balancer so a client keeps hitting the node that holds its socket.
Step 2
Add a pub/sub backplane
Wire servers to Redis, Kafka, or NATS so a message published on one node reaches every node.
Step 3
Fan out locally
On each server, subscribe to relevant channels and forward received messages to that server's local sockets only.
Step 4
Share presence and rooms
Store room membership and online presence in a shared store so any node knows where to route.
Step 5
Plan reconnects and draining
Design idempotent reconnection and connection draining so scaling and restarts don't lose clients.
What Interviewer Expects
- Recognition that WebSockets are stateful, long-lived connections
- Need for sticky sessions or L4 load balancing
- Understanding of a pub/sub backplane for cross-server broadcast
- Shared presence or room store for global membership
- Handling reconnection and graceful node draining
Common Mistakes
- Assuming a stateless round-robin load balancer works for sockets
- Keeping room state only in one server's memory
- Forgetting the backplane so cross-server messages never arrive
- Not planning reconnection when a node is drained or crashes
- Ignoring backpressure when one server fans out to many clients
Best Answer (HR Friendly)
“You run many socket servers behind a load balancer that keeps each user glued to the same server, and connect the servers with a shared message bus so a message sent to one can reach users on all of them. You also track who is online in a shared store and handle reconnections when servers restart.”
Code Example
const sub = redis.duplicate();
sub.subscribe('room:general');
// Broadcast: publish so every node receives it
function broadcast(msg) {
redis.publish('room:general', JSON.stringify(msg));
}
// Each node fans out to its own local sockets
sub.on('message', (channel, payload) => {
for (const ws of localRoomClients.get('general') || []) {
ws.send(payload);
}
});Follow-up Questions
- Why do WebSockets need sticky sessions when HTTP APIs often don't?
- How would you track presence across many servers?
- What are the trade-offs of Redis vs Kafka as a backplane?
- How do you drain connections gracefully during a deploy?
- How do you handle backpressure when broadcasting to millions of sockets?
MCQ Practice
1. Why is a plain round-robin load balancer problematic for WebSockets?
A WebSocket is a long-lived stateful connection, so the client must keep reaching the same server that holds its socket.
2. What is the role of a pub/sub backplane in scaling WebSockets?
Since clients for one room are spread across nodes, the backplane relays messages so every node can fan out to its local sockets.
3. Where should room membership and presence be stored in a multi-server setup?
A shared store gives every node a global view of who is online and which rooms they belong to.
Flash Cards
Why sticky sessions for WebSockets? — The socket is stateful and lives on one server, so the client must keep reaching that same node.
What is a pub/sub backplane? — A shared bus (Redis/Kafka/NATS) that relays messages between socket servers so any can broadcast to all clients.
How does each server broadcast? — It publishes to the backplane; every node subscribes and fans the message out to its own local sockets.
Where is presence stored? — In a shared store so all nodes have a global view of online users and room membership.