Why Redis Beats Databases for Job Queues in Multi‑Server Apps


Background jobs are essential in modern backends (Laravel, Node.js, Spring). Email sending, file processing, data syncs, reports, and API calls are best handled asynchronously. The core question:

Should job queue data live in a traditional database or in Redis?

Redis is the better choice for multi‑server systems. Here’s why.

What a Job Queue Actually Stores

Job queues store operational state, not business data:

  • Job payload (class + serialized data)
  • Queue name
  • Status (waiting, reserved, delayed)
  • Retry attempts
  • Timeout / visibility window

Characteristics:

  • Short‑lived data
  • High read/write frequency
  • Shared across many workers
  • Not required long‑term for reporting

Relational databases are not optimized for this workload.

Multi‑Server Reality

Production systems usually have multiple servers and many workers. Workers start, stop, and crash independently. Your queue must support distributed coordination, atomic reservation, fast push/pop, and safe recovery. Redis excels here.

Why Redis Fits Better

1. In‑Memory Speed

  • Microsecond operations
  • O(1) push/pop for queue commands
  • No disk I/O bottlenecks

Databases incur disk access, index scans, and locks—latency becomes a bottleneck at scale.

2. Atomic Operations Prevent Races

Redis provides atomic primitives (LPUSH, RPOP, BRPOP) and sorted sets for delays. Guarantees:

  • One job per worker
  • No duplicates
  • No custom locking logic

Database queues require SELECT ... FOR UPDATE, status flags, and retry cleanup—more complexity and risk of bugs.

3. Built for Distributed Systems

All workers across servers share the same Redis instance/cluster. State is visible instantly and coordination is lightweight. Databases suffer lock contention, deadlocks, and polling CPU overhead.

4. Clean Failure & Retry Handling

Redis job state: Ready → Reserved → Completed. Delayed jobs are separate, and automatic re‑queue occurs if a worker crashes. Database queues often leave jobs stuck in “processing” requiring manual cleanup.

5. Protects Your Business Database

Reserve the database for business data, transactions, reporting, and audits. If jobs live there:

  • Queue traffic competes with user traffic
  • Background spikes increase API latency
  • More workers increase DB pressure

Redis isolates operational load from business workload.

6. Scales Predictably

AspectRedisDatabase
Add workersLow overheadHigh contention
Add serversSafeRisky
ThroughputVery highLimited
Failure handlingBuilt‑inManual

What About Durability?

Redis is in‑memory by default with optional persistence (AOF/RDB); a small risk of job loss exists in catastrophic failures. Databases are fully durable.

Jobs are usually re‑creatable, while business data is not. The rule of thumb:

Jobs belong in Redis. Business state belongs in the database.

When a Database Queue Is OK

  • Low traffic
  • Single server
  • Simplicity over throughput
  • Limited operational scale

Beyond this, Redis is the safer long‑term choice.

Laravel Migration Playbook

1) Enable Redis Queues

QUEUE_CONNECTION=redis
  • Verify connection in config/queue.php
  • Set an appropriate retry_after

2) Run Horizon on Each Worker Server

php artisan horizon
  • Restrict dashboard access via HorizonServiceProvider gate

3) Tune Supervisors

  • Configure config/horizon.php queues
  • Set balancing strategy (auto, local)
  • Define min/max processes per queue

4) Make Jobs Idempotent

  • Use upserts/existence checks
  • Avoid duplicate writes or charges
  • Apply WithoutOverlapping for resource keys
  • Use ShouldBeUnique / ShouldBeUniqueUntilProcessing where appropriate

5) Timeouts & Backoff

  • Worker --timeout < max job runtime
  • Configure backoff for transient failures

6) Operations

  • Run scheduler (schedule:run) on a single server
  • Restart workers after env/config changes (queue:restart, horizon:terminate)
  • Monitor throughput, retries, failures in Horizon

Common Pitfalls & Fixes

  • Jobs retry concurrently → add idempotency + WithoutOverlapping
  • Long jobs re‑appear → increase retry_after, adjust worker --timeout
  • Stuck jobs → check Redis memory, supervisor config, and backoff
  • Horizon 403 → whitelist users via HorizonServiceProvider gate

FAQ

Can multiple servers run workers safely?

Yes. With shared Redis, reservation is atomic. Design for at‑least‑once processing.

Will the same job ever run twice?

It can on crashes or short visibility windows. Make jobs idempotent and tune timeouts.

Should I store jobs in my database?

Only for low‑traffic or single‑server scenarios where durability is critical. Redis scales better.

Final Recommendation

For multi‑server apps with many workers and real‑time/high‑volume tasks, Redis is the right architectural choice for job queues. It delivers speed, safety, scalability, and cleaner failure handling—while keeping your database focused on business data.