Stop 14 · Real-time CommunicationTopics · 6/6

Real-time Scaling Challenges

Part of the Backend Developer Roadmap

In short

Real-time works beautifully on one server. Add a second server behind a load balancer and suddenly half your users stop getting messages. Here's why, and the fix.

The specific difficulties of scaling WebSocket connections horizontally — since a client stays connected to one specific server instance, broadcasting to all clients requires coordination across instances.

The blob balances far too many plates at a wedding while a second waiter arrives to help.

Think of it like this

Waiters at a big wedding

One waiter can serve the tables he's standing near. Hire a second waiter for the other hall, and a guest in hall A asking to 'send sweets to my cousin' fails, because the cousin is in hall B. Waiters need a shared walkie channel to pass messages between halls.

Watch it happen

Riya and Aman on different servers

Riya
Server 1
Redis
Server 2

chat "hello"

1/5The load balancer put Riya's socket on Server 1. She sends a message to the room.

The big ideas

What you need to know

Share messages between servers

Each server only holds its own sockets. A pub/sub backbone like Redis passes events between all of them.

Sticky sessions

Long polling sends many requests per client. They must hit the same server, so turn on sticky sessions at the load balancer.

Connections cost memory

Each open socket holds memory and a file descriptor. Plan capacity by concurrent connections, not requests per second.

Reconnect storms

Deploy a new version and every client reconnects at once. Add random jitter to client retries so they spread out.

See it in code

Walk through the code

ts
1import { Server } from "socket.io";2import { createClient } from "redis";3import { createAdapter } from "@socket.io/redis-adapter";4 5const pubClient = createClient({ url: process.env.REDIS_URL });6const subClient = pubClient.duplicate();7await Promise.all([pubClient.connect(), subClient.connect()]);8 9const io = new Server(3000, { adapter: createAdapter(pubClient, subClient) });10// io.to("room-7").emit(...) now reaches sockets on every server

1/2Two Redis connections: one to publish broadcasts, one to listen for broadcasts from other servers.

Your emit code doesn't change at all. The adapter quietly forwards every room broadcast through Redis to the other instances.

Save yourself the pain

Common mistakes

Oops

Testing real-time features only with one local server.

Do this instead

Run two instances on different ports behind a simple proxy before launch, and test cross-server messages.

Oops

Keeping online-user lists in a JavaScript Map on each server.

Do this instead

Store presence in Redis with expiry, so every server sees the same list.

Your mission

Break it with two servers, then fix it

~40 min

Quick check

Why does a chat message fail to reach a user on another server without an adapter?

Go deeper

  1. 1Diagram the problem: a message needs to reach clients connected to different server instances.
  2. 2Learn how a Redis pub/sub adapter solves this for Socket.io across multiple instances.
  3. 3Understand sticky sessions and why load balancers need special config for WebSocket traffic.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge