Does your app poll the database every second to check for new messages? That wasted bandwidth, server load, and lag is killing your user experience. We see it every week in projects that land on our desk: chat apps that feel stuck, notifications that arrive minutes late, servers that spike with just 10 concurrent users. The problem isn't the feature; it's the architecture.
Redis Pub/Sub is a lightweight, blazing-fast messaging pattern built into Redis. It lets you push a message to every connected client on a channel in real time, without custom WebSocket servers or expensive third-party services. At Meteora Web, we've used it for years in chats, push notifications, dashboard updates, and microservice synchronization. And it's cheap: often you already have a Redis instance for caching.
This guide skips the theory. You'll get the why it works, the code to make it work, its limits, and a production-ready integration strategy. Let's start with the real problem: you want a chat that doesn't kill your server every time someone types 'hello'.
What is Redis Pub/Sub and why does it beat polling?
Redis Pub/Sub is a publish/subscribe messaging system. Three actors: a publisher sends a message on a channel, a subscriber listens to that channel, and Redis acts as the broker. The publisher doesn't know who's listening; the subscriber receives the message instantly without asking.
Sponsored Protocol
Compare that to classic polling: the frontend calls the API every 2 seconds 'any new messages?'. The server queries the database, replies 'no' 29 times out of 30. You waste CPU, bandwidth, and the average delay is 1 second (if polling every 2 seconds). With Pub/Sub, the server pushes the message only when there is one, and the client gets it in milliseconds.
How channels work
A channel is a string that acts as a topic. Subscribers subscribe to one or more channels. Publishers write to a channel. Redis distributes the message to all active subscribers. That's it. No buffer, no queue: the message lives only in flight. If a subscriber isn't connected at that moment, it loses the message. This is the first limit to understand.
Difference from direct WebSocket
You can implement a custom WebSocket server in Node.js or PHP and handle connections directly. But then you have to manage connection state, reconnection, room broadcast. Redis Pub/Sub gives you broadcast out of the box: every subscriber on a channel gets the message. If you have multiple WebSocket servers (horizontal scaling), Redis Pub/Sub becomes the glue between them. One server publishes; another server (that has the actual clients) receives and forwards the message.
Sponsored Protocol
How to implement a basic chat with Redis Pub/Sub?
Let's see the code. We'll use Node.js with the redis library (v4+).
Install the client
npm install redisThen create two scripts: one that publishes messages (e.g., when a user sends a message) and one that listens (e.g., the WebSocket server that forwards to browsers).
Publisher code
import { createClient } from 'redis';
const publisher = createClient();
await publisher.connect();
// When a user sends a message on channel 'chat:room:123'
const message = JSON.stringify({ user: 'Mario', text: 'Hello!', timestamp: Date.now() });
await publisher.publish('chat:room:123', message);
await publisher.quit();Subscriber code (WebSocket server)
import { createClient } from 'redis';
const subscriber = createClient();
await subscriber.connect();
await subscriber.subscribe('chat:room:123', (message) => {
// message is the JSON-stringified payload
const data = JSON.parse(message);
// Forward to all WebSocket clients connected to this room
wsRoom.send(JSON.stringify({ type: 'new_message', data }));
});
// Keep connection openImportant: the subscriber must stay connected, so don't call quit(). In production, run it as a separate process or worker.
Sponsored Protocol
That's the core. The chat works: a client sends a message to the backend (HTTP or WebSocket), the backend saves it to the database (optional) and publishes to Redis. The subscriber on the other server receives it and forwards to the target client. Real-time, done.
What are the limits of Redis Pub/Sub and how to handle them?
Redis Pub/Sub does not guarantee message persistence. If a subscriber disconnects, the message is lost. For a non-critical chat, that's fine (users reload the history from the database on reconnect). But for notifications that must reach offline users, you need Redis Streams (consumer groups with acknowledgments). At Meteora Web, when reliability is required, we combine the two: Pub/Sub for low latency when online, Streams for deferred delivery.
Horizontal scalability with fan-out pattern
If you have multiple WebSocket servers, each server runs a subscriber on Redis. When a publisher sends a message on a channel, all subscribers receive it. But this means every server forwards it to all its clients, including those not in the right room. You need to filter: the server-side subscriber knows which clients are connected to which rooms. It receives the message, checks the room, and forwards only to relevant clients. Simple bridge pattern.
Sponsored Protocol
For high availability, use Redis Cluster or Redis Sentinel. We've handled hundreds of thousands of messages per minute with Pub/Sub, but for extreme loads consider Kafka or RabbitMQ.
How to integrate Redis Pub/Sub with a real web app (e.g., Laravel Reverb)
If you use Laravel, you don't have to reinvent the wheel. Laravel Reverb (first-party WebSocket) is built on Redis Pub/Sub for broadcasting. Define an event, publish it on a Redis channel, and Reverb listens and pushes via WebSocket. Example:
Laravel event
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(public string $room, public array $data) {}
public function broadcastOn(): array
{
return [new PrivateChannel('chat.'.$this->room)];
}
}In your controller: event(new MessageSent('room123', $messageData));
Laravel publishes to Redis (thanks to the broadcast driver), Reverb listens and pushes to connected clients. All configurable in config/broadcasting.php. We used this for a booking platform with real-time updates — it worked flawlessly with thousands of simultaneous users.
For Node.js fans, we built a proprietary platform to manage social media presence for multiple clients: we used Redis Pub/Sub to sync posts between different servers. Zero extra cost, linear scalability.
Sponsored Protocol
What to do next
You now have enough to take action. Here are your concrete next steps:
- Check if you already have Redis in production (often yes, for caching). If so, you already have the Pub/Sub server at no extra cost.
- Install the Redis client in your language (Node.js, PHP, Python…). The official Redis documentation (redis.io) is the ultimate reference.
- Replace polling in your chat or notifications with a subscriber script that listens to a channel. Then update the frontend to use WebSocket (e.g., Socket.io client) connected to your backend.
- Decide if you need persistent messages: if yes, pair Redis Streams for offline messages. Otherwise, Pub/Sub is enough.
- Load test: use redis-cli monitor or redis-benchmark to check latency.
- Read our pillar guide on Redis and Caching Strategies to see how Pub/Sub fits with caching and other patterns.
At Meteora Web, we started with a clothing store where we updated prices in real time across three different storefronts. Today, Pub/Sub is our go-to starter for every real-time feature. If you'd like to discuss your use case, let's talk numbers: what does your current polling cost? How much would you save? The rest is just code.