Real-time messages reach only some users after scaling out
“With one instance everything worked. After adding a second, chat messages, notifications, and presence updates reach some users and silently skip others, and which ones changes on every reconnect.”
THE PRINCIPLE
Connection state is local to one process; fan-out needs a shared backplane that every instance publishes to and subscribes from.
FIRST MOVES
- Confirm it's routing, not a bug: log the instance ID with every connect and every emit, then compare sender and recipient.
- Add a pub/sub backplane. In Socket.IO, swap the default in-memory adapter for a shared one (Redis, Redis Streams, Postgres, cloud pub/sub). With raw WebSockets, publish to Redis or NATS and have each instance deliver to its local sockets.
- Keep sticky sessions only where the transport needs them. Socket.IO's HTTP long-polling requires them; WebSocket-only transports don't.
- Address users and topics, not socket IDs: join rooms such as user:42 so any instance can target them.
- Know that plain Redis pub/sub is fire-and-forget. While a subscriber is disconnected, its messages are lost, so recover with replay from a stream or an HTTP snapshot.
TOOLS: THEN → NOW
Sticky sessions as the scaling fixSticky sessions for long-polling only, plus an adapter or broker for fan-out
Socket.IO Redis adapter on classic pub/subSharded adapter (Redis 7 sharded pub/sub), or the Redis Streams adapter when you need connection state recovery
PATTERN SNAPSHOT
import { createClient } from "redis";
import { Server } from "socket.io";
import { createShardedAdapter } from "@socket.io/redis-adapter";
const pubClient = createClient({ url: process.env.REDIS_URL });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
const io = new Server({ adapter: createShardedAdapter(pubClient, subClient) });
// Any instance can now reach a user wherever they are connected.
io.to(`user:${userId}`).emit("notification", payload);CLOSE THE AI. EXPLAIN THIS.
Why don't sticky sessions alone fix a broadcast that misses users on other instances?HOW IT WORKS UNDERNEATH
RELATED SYMPTOMS
SOURCES
Guide reviewed