Limited Time Offer: 40% off

Redis Pub/Sub

Redis Pub/Sub delivers real-time messages to subscribers. Learn how to publish, subscribe, and choose between Pub/Sub and Streams.

Redis Pub/Sub is a messaging system built into Redis. Publishers send messages to named channels. Any client subscribed to that channel receives the message immediately. There is no queue, no persistence, and no delivery confirmation.

How it works

When a client subscribes to a channel, Redis registers that connection as a listener. When another client publishes a message to the same channel, Redis pushes it to every active subscriber in real time.

Messages are not stored. If no subscriber is connected when a message is published, the message is gone. Subscribers that connect later, or that reconnect after a disconnect, will not see messages they missed. This is the core trade-off of Pub/Sub: low latency in exchange for no durability.

Basic commands

Open a subscriber in one terminal:

127.0.0.1:6379> SUBSCRIBE price-updates
1) "subscribe"
2) "price-updates"
3) (integer) 1

The three-part reply confirms the subscription. The fields are: the message type, the channel name, and the number of channels currently subscribed.

Once subscribed, the connection enters a blocking listen mode. It cannot issue other commands. In a separate terminal, publish a message:

127.0.0.1:6379> PUBLISH price-updates "BTC:65420"
(integer) 1

The return value is the number of subscribers that received the message. Back in the subscriber terminal:

1) "message"
2) "price-updates"
3) "BTC:65420"

Again, three parts: the message type (message), the channel name, and the message body.

To unsubscribe from a specific channel:

127.0.0.1:6379> UNSUBSCRIBE price-updates

Calling UNSUBSCRIBE with no arguments removes all subscriptions on that connection.

Pattern subscriptions

PSUBSCRIBE subscribes to all channels matching a glob pattern. This is useful when channels follow a naming convention:

127.0.0.1:6379> PSUBSCRIBE notifications.*
1) "psubscribe"
2) "notifications.*"
3) (integer) 1

This will match notifications.email, notifications.sms, notifications.push, and so on. When a message arrives, the reply includes four parts instead of three:

1) "pmessage"
2) "notifications.*"
3) "notifications.email"
4) "New message from support"

The extra field is the actual channel name that matched the pattern. To remove the pattern subscription:

127.0.0.1:6379> PUNSUBSCRIBE notifications.*

Listing subscriptions

The PUBSUB command family lets you inspect active subscriptions on the server.

List all active channels (channels with at least one subscriber):

127.0.0.1:6379> PUBSUB CHANNELS
1) "price-updates"
2) "notifications.email"

You can pass a pattern to filter results:

127.0.0.1:6379> PUBSUB CHANNELS notifications.*
1) "notifications.email"

Check how many subscribers a channel has:

127.0.0.1:6379> PUBSUB NUMSUB price-updates notifications.email
1) "price-updates"
2) (integer) 3
3) "notifications.email"
4) (integer) 1

Count the number of active pattern subscriptions:

127.0.0.1:6379> PUBSUB NUMPAT
(integer) 2

Using Pub/Sub in Python

The redis-py library provides a PubSub object that manages a dedicated connection for subscriptions.

Subscriber:

PYTHON
import redis
import threading

r = redis.Redis(host="localhost", port=6379, decode_responses=True)
pubsub = r.pubsub()
pubsub.subscribe("price-updates")

def listen():
    for message in pubsub.listen():
        if message["type"] == "message":
            print(f"Received: {message['data']}")

thread = threading.Thread(target=listen, daemon=True)
thread.start()

The connection used by a PubSub object is dedicated to subscriptions. You cannot issue regular Redis commands on it while it is subscribed. Use a separate redis.Redis() instance for other commands.

pubsub.listen() is a blocking generator. Running it on a background thread keeps your main program free. For pattern subscriptions, replace subscribe() with psubscribe().

Publisher:

PYTHON
import redis

r = redis.Redis(host="localhost", port=6379, decode_responses=True)
r.publish("price-updates", "BTC:65420")

Publishing uses an ordinary connection and returns the subscriber count.

Using Pub/Sub in Node.js

With ioredis, create a separate client instance for subscriptions:

JAVASCRIPT
import Redis from "ioredis";

const publisher = new Redis();
const subscriber = new Redis();

await subscriber.subscribe("price-updates");

subscriber.on("message", (channel, message) => {
  console.log(`[${channel}] ${message}`);
});

// From the publisher client:
await publisher.publish("price-updates", "BTC:65420");

The subscriber client is dedicated to subscriptions once subscribe() is called. All other commands go through publisher (or any other client instance).

With node-redis, the pattern is similar: call client.subscribe(channel, handler) on a client that was created with client.duplicate() so it gets its own connection.

The fire-and-forget limitation

Pub/Sub is a broadcast mechanism, not a message delivery system. There is no acknowledgment, no retry, and no persistence. A message published when zero subscribers are connected produces no error. The message is discarded.

Subscribers that disconnect and reconnect will not receive messages published during the gap. If your application cannot tolerate message loss, Pub/Sub is the wrong tool.

Pub/Sub vs Redis Streams

Redis Streams (XADD, XREAD) were added to address the limitations of Pub/Sub. The right choice depends on whether you need delivery guarantees.

Pub/SubRedis Streams
Message persistenceNoYes
Missed messages on reconnectLostReplayable
Consumer groupsNoYes
AcknowledgmentNoYes (with consumer groups)
Pattern matchingYes (PSUBSCRIBE)No (use key naming)
LatencyLowerSlightly higher

Use Pub/Sub when you are broadcasting real-time events where missing a message is acceptable: live dashboards, chat presence indicators, cache invalidation signals, or pushing config changes to a fleet of workers.

Use Streams when you need reliable delivery: event sourcing, job queues, audit logs, or any case where a consumer must process every message exactly once.

Pub/Sub vs message queues

Pub/Sub broadcasts to all active subscribers at once. It is not a work queue. If three workers are subscribed to a channel, all three receive every message. There is no built-in way to distribute work across them.

If you need task distribution, at-least-once delivery, dead letter queues, or integration with other systems, a dedicated message broker (RabbitMQ, Amazon SQS, Google Pub/Sub) is a better fit. Redis Streams with consumer groups can also fill this role if you are already running Redis and the feature set is sufficient.

Quick reference

CommandDescription
SUBSCRIBE channel [channel ...]Subscribe to one or more channels
UNSUBSCRIBE [channel ...]Unsubscribe from channels (all if omitted)
PUBLISH channel messagePublish a message to a channel
PSUBSCRIBE pattern [pattern ...]Subscribe using a glob pattern
PUNSUBSCRIBE [pattern ...]Unsubscribe from patterns
PUBSUB CHANNELS [pattern]List active channels
PUBSUB NUMSUB [channel ...]Subscriber count per channel
PUBSUB NUMPATNumber of active pattern subscriptions