100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Scaling with the Redis Adapter

Learn how the Redis adapter uses Redis's pub/sub to synchronize rooms and broadcasts across multiple Socket.IO server instances, enabling true horizontal scaling.

Rooms & ScalingAdvanced10 min readJul 10, 2026
Analogies

Why You Need It

As established with the default in-memory adapter, a single Node.js process cannot deliver room broadcasts to sockets connected to a different process, which becomes a hard requirement to solve the moment you run more than one Socket.IO server instance behind a load balancer for availability or throughput. The @socket.io/redis-adapter package solves this by having every server instance both publish outgoing broadcast events to a shared Redis pub/sub channel and subscribe to that same channel, so when instance A calls io.to(room).emit(), the event is published to Redis, and every other instance (including A itself) receives it and delivers it to any locally-connected sockets that are members of that room.

🏏

Cricket analogy: It's like a national broadcaster's central feed that every regional commentary booth subscribes to and also pushes updates into — a wicket called at the Chennai booth is instantly relayed through the central feed to the Mumbai booth's live commentary, rather than each city working in isolation.

javascript
// npm install @socket.io/redis-adapter redis
import { createClient } from 'redis';
import { createAdapter } from '@socket.io/redis-adapter';
import { Server } from 'socket.io';

const pubClient = createClient({ url: 'redis://redis-cluster:6379' });
const subClient = pubClient.duplicate();

await Promise.all([pubClient.connect(), subClient.connect()]);

const io = new Server(httpServer, {
  adapter: createAdapter(pubClient, subClient),
});

// Application code is unchanged — broadcasts now work across all instances
io.on('connection', (socket) => {
  socket.on('join-room', (room) => socket.join(room));
});
io.to('room-42').emit('update', { status: 'live' });

Two Separate Redis Clients

The adapter requires two distinct Redis client connections — a pubClient for publishing and a subClient for subscribing — because a single Redis connection that has issued a SUBSCRIBE command enters a special mode where it can no longer execute regular commands like PUBLISH; this is a fundamental constraint of the Redis protocol, not a Socket.IO design choice. The idiomatic pattern is to create one client and .duplicate() it for the second role, which reuses the same connection configuration (host, auth, TLS) without re-specifying it.

🏏

Cricket analogy: It's like a stadium PA needing a separate microphone line from its speaker line — you can't broadcast an announcement and simultaneously listen for the umpire's radio call over the exact same physical wire.

Sticky Sessions Are Still Required

The Redis adapter solves cross-instance broadcasting, but it does not eliminate the need for sticky sessions (also called session affinity) at the load balancer level when using HTTP long-polling, because a single logical Socket.IO connection may issue multiple sequential HTTP requests that must all land on the same server process to maintain connection state. With WebSocket-only transport this concern mostly disappears since the connection is a single persistent TCP connection, but most production setups still configure sticky sessions (e.g., via ip_hash in nginx or cookie-based affinity in AWS ALB) as a safety net for polling fallback and for the initial HTTP handshake.

🏏

Cricket analogy: It's like requiring the same match referee to officiate every session of a Test match rather than swapping referees mid-day — even with perfect communication between referees (Redis), continuity of who's actually watching the pitch still matters for consistent decisions.

Forgetting sticky sessions is one of the most common production bugs when adding the Redis adapter: teams add Redis, assume scaling is 'solved', but still see intermittent connection failures because the load balancer round-robins polling requests across instances that don't share in-flight HTTP session state.

Beyond Redis, Socket.IO also supports adapters backed by MongoDB, Postgres, and a cluster-adapter for Node.js's built-in cluster module — the choice usually comes down to what infrastructure you already operate and its latency characteristics, since Redis pub/sub is typically the lowest-latency option.

  • The Redis adapter enables room broadcasts to reach sockets connected to any server instance in a multi-process cluster.
  • It works by having every instance publish and subscribe to shared Redis pub/sub channels.
  • Two separate Redis clients are required (pub and sub) because a subscribed connection can't issue other commands.
  • The idiomatic setup uses client.duplicate() to create the second connection with identical config.
  • Application-level room/broadcast code (io.to(room).emit()) requires no changes when adding the Redis adapter.
  • Sticky sessions at the load balancer are still needed, especially for HTTP long-polling fallback and the initial handshake.
  • Alternatives exist (MongoDB adapter, Postgres adapter, cluster adapter) depending on existing infrastructure.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#SocketIOStudyNotes#ScalingWithTheRedisAdapter#Scaling#Redis#Adapter#Need#StudyNotes#SkillVeris#ExamPrep