nikhil-patil
#redis #websockets #socket-io #scaling #backend

Scaling WebSockets with Redis Pub/Sub

How we built a horizontally scalable real-time sports scoring system using Socket.io and Redis Pub/Sub

5 min read min read

The Problem

A single Node.js WebSocket server can't scale horizontally. If user A is connected to server 1 and user B is connected to server 2, a message sent to server 1 never reaches user B.

The Solution: Redis Pub/Sub

Redis acts as a message broker between server instances. When any server receives a score update, it publishes to Redis. All servers are subscribed and broadcast to their connected clients.

const { createClient } = require('redis');
const { Server } = require('socket.io');

const publisher = createClient({ url: process.env.REDIS_URL });
const subscriber = createClient({ url: process.env.REDIS_URL });

await publisher.connect();
await subscriber.connect();

// When score update comes in
app.post('/score-update', async (req, res) => {
  const { matchId, score } = req.body;
  await publisher.publish('score-updates', JSON.stringify({ matchId, score }));
  res.json({ success: true });
});

// All server instances subscribe and broadcast to their clients
await subscriber.subscribe('score-updates', (message) => {
  const data = JSON.parse(message);
  io.to(`match:${data.matchId}`).emit('score', data.score);
});

Result

Any number of Node.js instances can now run behind a load balancer. Every connected client receives updates regardless of which server they're on.