Official documentation for publish/subscribe messaging. Also read the Streams section for durable messaging. Read →
Redis pub/sub lets parts of your app publish messages to channels. Other parts subscribe and receive them in real time. Use for: live notifications, cache invalidation across servers, real-time dashboards.
import Redis from 'ioredis';
const publisher = new Redis(process.env.REDIS_URL);
const subscriber = new Redis(process.env.REDIS_URL); // separate connection required
// Publisher
await publisher.publish('user:status', JSON.stringify({ userId: 123, status: 'online' }));
// Subscriber (blocks this connection for receiving only)
subscriber.subscribe('user:status');
subscriber.on('message', (channel, msg) => {
const data = JSON.parse(msg);
// broadcast to WebSocket clients, etc.
});
Redis pub/sub is fire-and-forget. If no subscriber is connected when you publish, the message is LOST. For guaranteed delivery, use RabbitMQ (Lesson 19) or Redis Streams.
| Use case | Redis | RabbitMQ |
|---|---|---|
| Caching | ✓ Built for this | Not appropriate |
| Real-time pub/sub (fire-and-forget) | ✓ Simple, fast | Overkill |
| Reliable job queues with retry | Needs BullMQ on top | ✓ Native |
| Guaranteed message delivery | Pub/sub: no | ✓ ACK-based |
| Complex routing logic | Not built-in | ✓ Exchanges + bindings |
npm install bullmq
import { Queue, Worker } from 'bullmq';
const connection = { host: 'redis', port: 6379 };
// Producer: add a job
const emailQueue = new Queue('emails', { connection });
await emailQueue.add('send-welcome', {
to: 'user@example.com', template: 'welcome'
}, { attempts: 3, backoff: { type: 'exponential', delay: 1000 } });
// Consumer: process jobs
const worker = new Worker('emails', async job => {
await sendEmail(job.data.to, job.data.template);
}, { connection });
worker.on('completed', job => console.log('Done:', job.id));
worker.on('failed', (job, err) => console.error('Failed:', err.message));
# Set max memory and eviction policy
redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
# Common policies:
# noeviction — errors when full (safe default)
# allkeys-lru — evict least recently used (good for pure caching)
# volatile-lru — evict LRU keys that have TTL set