RedisStorage is a production-ready storage backend that uses Redis or Valkey for distributed, persistent job queue storage with atomic operations and pub/sub notifications.
Constructor
Configuration
Redis connection URL. Falls back to
process.env.REDIS_URL if not provided.Supports standard Redis URL formats:redis://localhost:6379redis://user:pass@host:port/dbrediss://for TLS connections
Prefix for all Redis keys used by the job queue. Allows multiple queue instances to share the same Redis database.All keys follow the pattern:
{keyPrefix}jobs, {keyPrefix}queue, {keyPrefix}processing:{workerId}, etc.Optional Pino logger instance for debugging and monitoring. If not provided, a no-op logger is used.
When to Use
RedisStorage is the recommended backend for:
- Production deployments: High availability and durability
- Distributed systems: Multiple worker processes or machines
- High throughput: Efficient atomic operations with Lua scripts
- Horizontal scaling: Add more workers without storage bottlenecks
- Leader election: Built-in support for single-reaper coordination
Compatibility
Redis 7+ or Valkey 8+ required for optimal performance. Uses
BLMOVE for blocking dequeue operations.- Redis 7.0+: Full support with blocking list operations
- Valkey 8.0+: Fully compatible Redis fork
- Redis 6.x: Not officially supported (missing BLMOVE)
Features
Atomic Operations
All critical operations use Lua scripts for atomicity:- Enqueue: Check for duplicates and add to queue atomically
- Complete: Set state, store result, remove from processing queue, and publish notification in one operation
- Fail: Similar to complete, but stores error instead
- Retry: Update state, move to queue, notify subscribers atomically
- Cancel: Delete job and publish event atomically
Pub/Sub Notifications
RedisStorage uses Redis pub/sub for real-time notifications:- Job notifications: Per-job channels for
enqueueAndWait()response - Event stream: Global events channel for monitoring and reaper
- Efficient routing: Only subscribes to channels when needed
Blocking Dequeue
RedisStorage uses Redis BLMOVE for efficient blocking dequeue:
- No polling: Workers sleep until jobs arrive
- Fair distribution: Redis handles FIFO ordering
- Connection pooling: Single blocking client handles all workers
Leader Election
Implements distributed leader election for reaper coordination:TTL Management
Results and errors are stored with TTL expiry:- Envelope format: 8-byte timestamp header + payload
- Lazy expiration: Checked on read, cleaned up by reaper
- Backward compatible: Falls back to reading legacy non-envelope entries
Example
Basic Usage
Multiple Queues with Key Prefixes
Distributed Workers
Redis Key Structure
With defaultkeyPrefix: 'jq:', RedisStorage uses these keys:
| Key | Type | Purpose |
|---|---|---|
jq:jobs | Hash | Job states (id → status:timestamp[:workerId]) |
jq:queue | List | Main job queue (FIFO) |
jq:processing:{workerId} | List | Per-worker processing queues |
jq:results | Hash | Job results with TTL envelope |
jq:errors | Hash | Job errors with TTL envelope |
jq:workers | Hash | Active worker registrations |
jq:notify:{jobId} | Pub/Sub | Per-job completion notifications |
jq:events | Pub/Sub | Global event stream |
Performance Considerations
Connection Pooling
RedisStorage creates three Redis connections:- Main client: All standard operations (enqueue, state updates, etc.)
- Blocking client: Dedicated connection for
BLMOVEoperations - Subscriber: Dedicated connection for pub/sub messages
Lua Script Caching
Scripts are loaded once duringconnect() and cached by SHA:
Batching
For bulk operations, usegetJobStates() instead of multiple getJobState() calls:
Testing
For testing, use theclear() method to reset Redis state:
Related
- MemoryStorage - In-memory storage for testing
- FileStorage - Persistent single-node storage
- Queue API - Queue setup with storage backends