Redis Pub/Sub with WebSockets for Scalable Messaging in NestJS

As your real-time application grows, a single WebSocket server may not be able to handle all clients efficiently. In a distributed system where multiple instances of your NestJS app are running, messages need to be shared across them seamlessly. This is where Redis Pub/Sub comes into play.

In this module, you’ll learn how to integrate Redis with NestJS WebSockets to enable scalable real-time communication using the publish/subscribe pattern.


Table of Contents

  1. Why Use Redis Pub/Sub with WebSockets?
  2. How Pub/Sub Works in Redis
  3. Installing Required Packages
  4. Setting Up Redis Pub/Sub in NestJS
  5. Integrating with WebSocket Gateway
  6. Broadcasting Across Instances
  7. Testing the Scalable Architecture
  8. Security and Best Practices
  9. Conclusion

Why Use Redis Pub/Sub with WebSockets?

When your application scales horizontally (multiple Node.js instances), Socket.IO alone can’t keep all clients in sync. For example, if user A is connected to Instance 1 and user B is on Instance 2, messages between them won’t be delivered unless the instances can share messages.

Redis Pub/Sub acts as a centralized broker to:

  • Publish messages from any instance
  • Distribute messages to all subscribing instances
  • Maintain real-time consistency across distributed systems

How Pub/Sub Works in Redis

The Publisher sends a message to a Redis channel.
The Subscribers (your app instances) listen to that channel and receive the message.

It’s a perfect pattern for broadcasting WebSocket messages across clusters or Docker containers.


Installing Required Packages

You’ll need the following:

bashCopyEditnpm install redis socket.io-redis
npm install --save-dev @types/redis

For NestJS with Socket.IO adapter:

bashCopyEditnpm install @nestjs/platform-socket.io @nestjs/websockets

Setting Up Redis Pub/Sub in NestJS

Use socket.io-redis to create a custom adapter.

Step 1: Create a Redis Adapter

tsCopyEdit// redis.adapter.ts
import { IoAdapter } from '@nestjs/platform-socket.io';
import { ServerOptions } from 'socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';

export class RedisIoAdapter extends IoAdapter {
  async createIOServer(port: number, options?: ServerOptions): Promise<any> {
    const server = super.createIOServer(port, options);

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

    await pubClient.connect();
    await subClient.connect();

    server.adapter(createAdapter(pubClient, subClient));

    return server;
  }
}

Step 2: Apply the Adapter in main.ts

tsCopyEdit// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { RedisIoAdapter } from './redis.adapter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useWebSocketAdapter(new RedisIoAdapter(app));
  await app.listen(3000);
}
bootstrap();

Integrating with WebSocket Gateway

Your WebSocket gateway doesn’t change much. Redis automatically handles message routing between app instances.

tsCopyEdit@WebSocketGateway({ cors: true })
export class ChatGateway {
  @WebSocketServer()
  server: Server;

  @SubscribeMessage('sendMessage')
  handleMessage(
    @MessageBody() payload: { room: string; message: string },
    @ConnectedSocket() client: Socket,
  ) {
    this.server.to(payload.room).emit('receiveMessage', {
      user: client.id,
      message: payload.message,
    });
  }
}

Broadcasting Across Instances

When a client sends a message, it’s published to Redis. Redis then forwards it to all other connected clients, regardless of the instance they’re on.

This enables:

  • Load balancing WebSocket traffic
  • Real-time chat apps with rooms
  • Microservices communication via WebSockets

Testing the Scalable Architecture

You can simulate this setup by:

  1. Running multiple instances of your NestJS app (e.g., on different ports)
  2. Connecting one client to each instance
  3. Sending a message from one client and verifying the other receives it

You’ll observe that Redis ensures real-time delivery even across app instances.


Security and Best Practices

  • Namespace Isolation: Use namespaces for multi-feature apps (/chat, /notifications, etc.).
  • Authentication: Validate JWT or sessions during connection using middleware or guards.
  • Error Handling: Gracefully manage Redis disconnections or failures.
  • Scaling: Redis handles a lot, but monitor performance under load.

Conclusion

Integrating Redis Pub/Sub with NestJS WebSockets provides a robust foundation for scalable real-time systems. Whether you’re building chat apps, collaboration tools, or live dashboards, Redis ensures consistency and performance in distributed environments.