Databases·8 min read·

Redis Pub/Sub: When to Use It and When Not

Use Redis pub/sub for live fan-out on one host, and skip it when you need persistence, retries, or consumer groups that Streams already provide.

NB

Netbay Infrastructure Team

Netbay Engineering

On this page

Redis pub/sub is a live radio. PUBLISH sends a message to every client currently SUBSCRIBEd on that channel. If nobody is listening, the message is gone. There is no backlog, no ACK, no consumer group, and no retry. That is the whole feature, and it is why pub/sub is both useful and the wrong default for background work.

Use it for fan-out that is allowed to drop: live dashboard ticks, a "reload config" signal, a chat presence ping. Do not use it for invoices, emails, or anything you would put in a queue. Redis Streams exist for that, and so does a table in Postgres.

A minimal publisher and subscriber

The subscriber is a long-lived connection. It cannot share the connection with GET and SET in most clients, because once SUBSCRIBE is issued the socket is in subscription mode. Open a second client.

bash
# terminal 1
redis-cli
SUBSCRIBE jobs:events
# reading messages...

# terminal 2
redis-cli
PUBLISH jobs:events '{"type":"reload","src":"admin"}'
# (integer) 1

The integer is the number of clients that received the message, not a guarantee they processed it. Zero means you shouted into an empty room. That is not an error. It is pub/sub working as designed.

In application code, keep the subscriber process small and crash-only. On restart it resubscribes and misses everything that happened while it was down.

javascript
const sub = redis.duplicate();
sub.subscribe('jobs:events');
sub.on('message', function (channel, raw) {
  const msg = JSON.parse(raw);
  if (msg.type === 'reload') loadConfig();
});

Pattern subscribe with PSUBSCRIBE jobs:* is convenient and easy to over-use. Every extra match is another payload on the socket. Prefer explicit channel names.

When pub/sub is the wrong tool

If the consumer can be offline, you need a log, not a radio. Redis Streams give you XADD, XREADGROUP, and XACK. A missed worker picks up pending entries after a crash. Pub/sub cannot do that. If you "fix" pub/sub by also writing the event to a list, you have invented a worse stream. Use Streams, or write a row in SQL and let a worker poll.

If you need at-least-once delivery, pub/sub is wrong. If you need ordering across reconnects, it is wrong. If you need multiple workers to split a backlog, it is wrong. If you need to replay last night's events, it is wrong.

Pub/sub is also a fan-out amplifier. One PUBLISH to a channel with 200 subscribers copies the payload 200 times on the server. On a small VPS that is CPU and RAM you could have spent on GET latency. Keep subscriber counts small. Do not attach a browser to Redis. Put a web socket server in front; let that server be the one Redis subscriber.

bash
# Streams for work that must not drop
XADD jobs:mail * to user@example.com template welcome
XGROUP CREATE jobs:mail workers 0 MKSTREAM
XREADGROUP GROUP workers w1 COUNT 10 BLOCK 5000 STREAMS jobs:mail >

That is a queue. Pub/sub is not a queue, even if the channel is named jobs.

Operational limits on a VPS

Pub/sub messages do not hit AOF or RDB. A restart drops in-flight fans. That is expected. Slow subscribers cause Redis to buffer output. client-output-buffer-limit pubsub exists because a stuck subscriber can grow Redis until maxmemory fights it.

bash
# /etc/redis/redis.conf
client-output-buffer-limit pubsub 32mb 8mb 60
timeout 0

INFO clients and CLIENT LIST show flags P for pub/sub. If a client has a huge omem, it is not keeping up. Kick it. Do not raise the buffer until the VPS swaps.

Bind still applies. A public 6379 plus SUBSCRIBE is a free firehose of whatever you publish, including session-shaped payloads if someone reused a channel. Keep Redis on 127.0.0.1. Lucknow DC01 L3/L4 filtering will not save a published pub/sub port.

Two application processes on the same VPS can share a channel without drama. Two VPS nodes can too, if you bind a private address and ACL the subscriber, but you still have no backlog. A rolling restart of subscribers drops every message published during the gap. That is acceptable for a "redraw the dashboard" ping. It is not acceptable for "charge this card." If you are about to add a retry loop around PUBLISH, stop and use Streams.

Pub/sub fan-out vs a durable stream PUBLISH live subscribers only no retry, no backlog XADD / XREADGROUP pending entries survive ACK, retry, replay offline consumer: use Streams live UI tick: pub/sub is enough

Takeaway

Pub/sub is live fan-out. Streams are work queues. If losing a message would cost money or a user-visible job, do not PUBLISH it. Try both on a Netbay VPS in Lucknow — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance