When to Use Redis Adapter vs Memory Adapter for Socket.io Scaling
Socket.io is stateful, so scaling beyond one process requires choosing between the in-process Memory Adapter and the Redis Adapter for cross-node broadcast. This guide compares the options and shows how to validate a Redis-backed deployment.
22 Jan 2026, 13:34 UTC

The moment you run two Socket.io processes behind a load balancer, rooms and broadcasts stop working across nodes. A client connected to Node A will never receive an event emitted from Node B unless the nodes share state. The decision is which adapter to use and whether you can accept the operational constraints that come with it.
Socket.io is stateful. The handshake creates a session that lives in the process handling the connection. Horizontal scaling therefore requires both session affinity and a cross-node broadcast mechanism.
Decision constraints
Before choosing an adapter, confirm these constraints:
- Sticky sessions are required at the load balancer for HTTP long-polling fallback. Without affinity, the handshake may land on one node and the next poll on another, producing a Session ID not found error.
- The Memory Adapter stores sockets and rooms in local RAM. It is fast but invisible to sibling processes.
- The Redis Adapter uses Redis Pub/Sub to propagate emits. It enables horizontal scaling at the cost of a network hop and an additional dependency.
Options compared
| Feature | Memory Adapter | Redis Adapter |
|---|---|---|
| Use case | Single process, development | Multi-node production |
| Synchronization | Local memory only | Redis Pub/Sub |
| Complexity | Built-in, zero config | Requires Redis clients and adapter |
| Latency | Zero network hop | Pub/Sub hop overhead |
| Scalability | Vertical only | Horizontal |
Trade-offs
Memory Adapter is optimal for local development and single-instance deployments. It avoids operational overhead and has the lowest latency because emits stay in process. The limitation is total: events emitted on one instance do not reach clients on another, and rooms are per-process.
Redis Adapter solves cross-node propagation. When a server emits to a room, the adapter publishes a message to Redis. All other servers receive it and forward to their local clients. This enables true horizontal scaling.
Costs to consider:
- Latency and throughput. Every broadcast incurs a Redis round trip. High-frequency updates can amplify this overhead.
- Reliability. Redis Pub/Sub becomes a single point of failure unless you run a cluster or Sentinel. If Redis is unavailable, cross-node messaging stops.
- Bandwidth. Large payloads replicated to every node can saturate Redis. Throttle or compress payloads for high-volume use cases.
Sticky sessions remain mandatory even with Redis. WebSocket upgrades usually succeed on the first node, but long-polling fallback relies on session affinity. Configure the load balancer to route by client IP or a cookie.
Concrete implementation
The following shows how to wire the Redis Adapter in a Node.js service. Run this on each Socket.io node with access to the same Redis.
npm install socket.io @socket.io/redis-adapter redis
const http = require('http');
const { Server } = require('socket.io');
const { createClient } = require('redis');
const { createAdapter } = require('@socket.io/redis-adapter');
const pubClient = createClient({ url: 'redis://localhost:6379' });
const subClient = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).catch(err => {
console.error('Redis connection error:', err);
});
const httpServer = http.createServer();
const io = new Server(httpServer, {
cors: { origin: '*' }
});
io.adapter(createAdapter(pubClient, subClient));
io.on('connection', socket => {
socket.on('join', room => socket.join(room));
});
httpServer.listen(3000);
Permissions required: network access to Redis from each app host, and read/write rights for the Redis user. Meaningful placeholders are the Redis URL and port. Do not hardcode credentials in source.
Validation
Check the setup without assuming it works:
- Start two instances on different ports, both using the same Redis.
- Connect a client to instance A and another client to instance B, joining the same room.
- Emit from instance A via the server API. Verify the client on instance B receives the event.
- Monitor Redis activity to confirm publish/subscribe traffic is flowing. Use the Redis CLI MONITOR command in a dev environment to observe messages on the adapter channels.
- Inspect load balancer logs to confirm session affinity is holding the handshake and polling to the same node.
Limitations
The Redis Adapter does not persist socket state. A node restart drops its local connections. Pub/Sub messages are not durable; subscribers must be online to receive them. For production, run Redis in a managed cluster with failover and monitor memory and bandwidth during traffic bursts.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.