Skip to content

Redis Down

Redis goes down — the cache layer disappears entirely

Redis is the shield between your app servers and your DB. At steady state it absorbs 80%+ of all reads. When it disappears, 1M reads/sec lands directly on 16 DB read nodes that were sized for 200k/sec. Without a plan, this is a cascading failure.


What happens without any protection

Redis goes down. App servers still receive 1M redirect requests/sec. Every request misses cache and falls through to DB.

Normal state:
1M reads/sec → Redis absorbs 800k → DB sees 200k/sec → 12.5k per node ✓

Redis down, no protection:
1M reads/sec → Redis fails → all 1M hit DB → 62.5k per node

Postgres handles ~10k-50k reads/sec per node depending on query complexity. At 62.5k/sec per node you are at or over the limit. Queries start queuing. Latency spikes. Connections pile up. DB nodes start timing out.

Now the app servers are waiting on timed-out DB connections. Those threads are held. New requests queue behind them. The queue grows faster than it drains. The system tips into cascading failure — each layer failing makes the next layer fail harder.


Problem 1 — No circuit breaker makes it worse

Without a circuit breaker, every request to the dead Redis waits for a timeout before falling back to DB. Say Redis timeout is 500ms.

1M requests/sec × 500ms timeout = every request stalls for 500ms
→ Latency jumps from ~5ms to ~500ms
→ Thread pool exhausted waiting for timeouts
→ DB gets hit with a thundering herd all at once when timeouts expire

The circuit breaker fixes this. After N consecutive Redis failures in T seconds, the circuit opens — app servers stop trying Redis entirely and go straight to DB without waiting for a timeout.

Redis healthy     → circuit closed  → requests go to Redis normally
Redis failing     → 5 failures in 10s → circuit opens
Circuit open      → requests skip Redis → go straight to DB → no 500ms wait
Redis recovers    → circuit half-opens → one test request to Redis
Test succeeds     → circuit closes → traffic back to Redis

With the circuit breaker, the fallback to DB is immediate. No wasted timeout overhead. Latency is higher than normal (DB is slower than Redis) but not catastrophically so.


Problem 2 — DB capacity under full load

Even with the circuit breaker, 1M reads/sec hitting the DB is too much. The numbers:

DB read capacity per node:     ~50k reads/sec (generous estimate)
Read nodes available:          16 (8 shards × 2 secondaries)
Total DB read capacity:        16 × 50k = 800k reads/sec

Incoming at peak:              1,000,000 reads/sec
Shortfall:                     200,000 reads/sec over capacity

The DB cannot absorb the full load even at best case. You are over capacity.

Auto-scaling helps but not fast enough — spinning up a new Postgres replica takes minutes. The traffic surge is immediate.


The fix — throttle at API Gateway

The API Gateway is the entry point for all traffic. When Redis goes down and DB is approaching capacity, the API Gateway rate-limits incoming read (redirect) requests:

Redis down → circuit breaker opens → DB load climbs
→ API GW detects DB latency spike (or Redis health check fails)
→ API GW throttles GET /:code requests
→ Returns 503 Service Unavailable to some percentage of redirect requests
→ DB load drops to sustainable level
→ System stays alive, degraded but functional

Availability takes a hit — some users get a 503 instead of a redirect. But the system does not collapse entirely. Creation still works. The DB does not cascade. When Redis recovers, throttling is lifted and full capacity is restored.

This is the correct trade-off: partial availability is better than total failure.


The full failure and recovery sequence

T=0s    Redis cluster goes down
T=0s    App servers start getting Redis connection errors
T=10s   Circuit breaker opens (5 failures in 10s threshold)
T=10s   All requests skip Redis, go straight to DB
T=10s   DB load: 1M reads/sec → nodes approaching capacity
T=15s   API GW detects DB latency spike → throttles read requests
T=15s   DB load drops to ~600k/sec → within capacity
T=15s   System running degraded: some 503s, higher latency, but alive

[Redis cluster recovers — say 20 minutes later]

T=20m   Redis nodes come back up
T=20m   Circuit breaker half-opens → sends test request to Redis
T=20m   Test succeeds → circuit closes
T=20m   API GW lifts throttling
T=20m   Traffic flows back to Redis → DB load drops to 200k/sec
T=20m   System fully restored

The trap — assuming auto-scaling saves you

Auto-scaling is not instant. Spinning up a new Postgres replica takes minutes — provisioning, WAL catch-up, health checks. The traffic surge is immediate. Auto-scaling is useful for gradual growth, not for sudden cache failure. The real protection is circuit breaker + API GW throttling, not auto-scaling.


Interview framing

"Redis down → circuit breaker opens immediately, requests skip Redis and go straight to DB. Without circuit breaker, 500ms timeouts per request cause thundering herd. DB can't absorb 1M reads/sec — API GW throttles redirect requests, returns 503 to some percentage. Partial availability beats total failure. When Redis recovers, circuit half-opens, test request succeeds, circuit closes, throttling lifts."