system-design · beginner
Cache Stampede — When Expiry Melts the Database
Start here
A cache stampede (also called dogpiling or a thundering herd on a cache key) is this failure mode:
A hot piece of data expires (or is missing). Hundreds or thousands of requests arrive at the same moment. Every request misses the cache and independently recomputes or reloads the same value from the database. The origin collapses under duplicate work.
You should care because the cache was supposed to protect the database. A stampede turns a normal expiry into a self-inflicted outage — often right after a deploy, a TTL boundary, or a cache restart.
What you will learn
- Define stampede / dogpile in plain English.
- Explain hot keys and synchronized expiry.
- Walk a timeline of a stampede second by second.
- Compare fixes: single-flight, locking, probabilistic early refresh, stale-while-revalidate, background refresh.
- See how TTL jitter reduces synchronized expiry.
- Work a homepage and product-detail example.
- Know metrics and failure modes of the fixes themselves.
- Decide when longer TTL alone is not enough.
What you should know first
| Topic | Why |
|---|---|
| Caching 101 | Hits, misses, TTL |
| Caching Strategies | Cache-aside miss path |
| Latency vs Throughput | Queues under overload |
Words you need before we begin
| Term | Plain English |
|---|---|
| Hot key | One cache key requested far more than others. |
| Miss | Cache does not have a usable value. |
| Stampede / dogpile | Many concurrent misses regenerate the same value. |
| Single-flight | Only one loader runs per key; others wait for its result. |
| Mutex / lock | Mechanism so only one worker enters a critical section. |
| Stale-while-revalidate | Serve slightly old data while refreshing in the background. |
| TTL jitter | Randomize expiry times so keys do not die together. |
| Origin | Database or service that produces the real value. |
| Thundering herd | Many waiters wake and rush a resource at once (related idea). |
Simple story: the shared answer sheet
A classroom of 200 students may copy the answer to question 1 from the board (cache).
When the teacher erases the board (TTL expiry):
- Without coordination, all 200 run to the library (database) for the same book page.
- The library stampede hurts everyone.
- Single-flight: one student fetches; others wait and copy that one answer.
- Early refresh: a monitor rewrites the board before class arrives, so nobody stampedes.
The problem: success that becomes failure
Healthy state
- Key
home:v3lives in Redis for 60 seconds. - Hit ratio is high.
- Database load is calm.
Stampede moment
At second 60.000, the key expires. In the next 50 ms, 5,000 requests arrive (homepage traffic).
Without protection:
- 5,000 cache misses
- 5,000 identical SQL queries or service calls
- Database CPU spikes
- Timeouts → retries → even more load
- Site appears “randomly down” every minute on the minute
Step-by-step explanation
Step 1 — Why hot keys matter
Not all keys stampede equally. A key hit once per minute can expire safely. A key hit 10,000 times per second will amplify a miss into a crisis.
Examples of hot keys:
- Homepage blob
- “Product of the day”
- Global feature-flag document
- Celebrity profile after a viral event
Step 2 — Synchronized expiry makes it worse
If thousands of keys share TTL = 3600 and were warmed together at deploy time, they may expire together → many stampedes or one giant origin spike.
Jitter: set TTL to 3600 + random(0..120) so expiries spread out.
Step 3 — Cold cache is a stampede cousin
After Redis restart or FLUSHALL:
- Every key misses
- Origin sees “everyone at once”
Step 4 — Fix A: single-flight (request coalescing)
Idea: for each key, only one in-flight load is allowed.
- Miss detected.
- Try to acquire “load lock” for key.
- Winner loads origin, fills cache, releases lock.
- Losers wait (or poll) and then read the filled cache (or share the winner’s result in-process).
Step 5 — Fix B: stale-while-revalidate
Store value + soft expiry + hard expiry:
- Before soft expiry: normal hit.
- Between soft and hard: serve stale, trigger one background refresh.
- After hard: must miss or block.
HTTP CDNs use related ideas (stale-while-revalidate cache directives).
Step 6 — Fix C: probabilistic early recomputation
Before expiry, each request has a small probability to refresh early:
- Most requests still hit.
- A few refresh “just in case.”
- Probability rises as expiry nears (XFetch-style algorithms).
Step 7 — Fix D: background warmers
A worker refreshes known hot keys on a schedule before TTL death.
Pros: predictable.
Cons: must know the hot set; wasteful if traffic disappears; still need jitter.
Step 8 — Fix E: longer TTL alone
Longer TTL reduces stampede frequency but:
- Increases staleness
- Does not fix cold-cache events
- Does not fix invalidation-driven mass deletes
Step 9 — Locks can stampede too
If 5,000 threads wait on one lock and all wake when it releases, you can get a thundering herd on the lock itself. Good designs:
- Only a few waiters
- Others serve stale
- Or sleep with jitter and recheck cache
Visual mental model
Stampede timeline
flowchart TB
H[Hot key expires] --> M[Many concurrent misses]
M --> D[Duplicate origin loads]
D --> O[Origin overload]
O --> T[Timeouts and retries]
T --> O
Learning question: Where should you collapse duplicate work?
Caption: Many misses must become one load.
Single-flight
flowchart LR
R1[Request 1] --> L{Lock key}
R2[Request 2] --> L
R3[Request 3] --> L
L -->|winner| DB[(Origin load)]
DB --> C[(Fill cache)]
C --> All[All requests get value]
Learning question: What happens if the winner crashes mid-load?
Caption: Locks need timeouts so waiters are not stuck forever.
Complete worked example: viral product page
Setup
- Key
product:42:view - TTL 30 seconds
- Peak 8,000 rps on that product during a TV mention
- Render costs 40 ms DB + 20 ms CPU
Without protection
Every 30 seconds: ~8,000 identical rebuilds → DB connection pool exhausts → checkout also fails (shared pool).
With protection
- TTL jitter 30–45 seconds.
- Single-flight per instance + Redis lock for cross-instance.
- Soft TTL at 20s: serve stale until 45s while one refresher runs.
- Alert if origin builds for
product:42exceed N/second.
Outcome
Origin builds drop to roughly one per refresh window; p99 stays flat through the viral spike.
How it works in production
Building blocks
- In-process single-flight maps
- Redis locks /
SET key NX EX - CDN edge stale-while-revalidate
- Sidecar warmers for top-N keys from analytics
Metrics
- Miss rate on hot key prefixes
- Concurrent origin loads per key (ideal near 1)
- Lock wait time
- DB CPU correlated with TTL boundaries (sawtooth pattern)
Ownership
When a stampede hits, know:
- Which key
- Which service owns the loader
- Whether to serve stale or fail closed
Failure modes
| Mode | Risk | Mitigation |
|---|---|---|
| Lock never released | Stuck misses | Lock TTL; safe release |
| All instances stampede (no distributed lock) | N× loads | Shared lock or edge cache |
| Serving forever-stale | Wrong data | Hard max age |
| Warmer storms | Self-DDoS | Rate limit warmers |
| Retry storms after timeout | Amplification | Budgeted retries + jitter |
Trade-offs
| Technique | Benefit | Cost |
|---|---|---|
| Single-flight | Collapse duplicate work | Lock complexity |
| Stale-while-revalidate | Smooth UX | Temporary wrongness |
| Early probabilistic refresh | No central lock | Extra refresh work |
| Background warmer | Predictable | Must track hot set |
| Longer TTL | Fewer expiries | Staleness |
Compare with related concepts
| Term | Relation |
|---|---|
| Thundering herd | General herd wake-up; stampede is herd on cache miss |
| Hot partition | Uneven load on one shard; may coexist with hot keys |
| Retry storm | Amplifies failures after timeouts |
| Cold start | Empty cache; stampede-like global miss |
Common misunderstandings
- “Just increase TTL to one day.”
- “Stampede only happens at big tech scale.”
- “Locks make everything slow.”
- “CDN means no stampede.”
- “Single-flight fixes correctness bugs.”
Check your understanding
Many concurrent misses reload the same hot key from origin
The cache runs out of disk sectors only
DNS TTL becomes infinite automatically
HTTPS is disabled
It spreads expiry times so fewer keys die at once
It encrypts cache values
It replaces all load balancers
It deletes the need for a database
Practice
Your news homepage key expires every 15 seconds. Traffic is 2,000 rps. Rebuild takes 100 ms and hits 12 queries.
- Estimate worst-case origin rebuilds per expiry without protection.
- Design single-flight across 20 app instances.
- Add soft/hard expiry numbers.
- List three metrics for a dashboard panel “stampede risk.”
- Decide: serve 5-second-stale homepage during refresh, or show an error page?
Revision summary
- Stampede = concurrent hot misses × expensive rebuild.
- Synchronized TTL and cold cache make it worse.
- Collapse duplicate loads (single-flight).
- Prefer serving stale briefly over melting origin.
- Jitter TTLs; warm carefully.
- Measure concurrent rebuilds per key, not only hit ratio.
Glossary
| Term | Definition | Example |
|---|---|---|
| Cache stampede | Concurrent miss herd on one key | Homepage expiry |
| Dogpile | Synonym for stampede | Same event |
| Hot key | Extremely popular key | product:42 |
| Single-flight | One loader per key | Lock + share result |
| Soft expiry | Age when refresh should start | 20s of 30s TTL |
| Hard expiry | Age when value must not be used | 45s max |
| Jitter | Randomized delay/TTL | ±10% TTL |
| Origin | Backing store/service | Primary DB |
| Coalescing | Merging duplicate work | One SQL not 5k |
| Warmer | Background refresh job | Cron top-100 keys |
Abbreviations and terminology
| Short | Full / note |
|---|---|
| TTL | Time To Live |
| rps | Requests per second |
| NX | “Not exists” lock pattern (SET NX) |
| SWR | Stale-While-Revalidate |
| CDN | Content Delivery Network |
| OOM | Out Of Memory |
What to learn next
Primary next lesson: Stale Cache After Write — Read-Your-Writes Failures
Also: CDN for edge-level caching and coalescing behavior.
Track: Data, Storage and Messaging
Previous: Cache Eviction Policies — LRU, LFU, TTL, and Friends
Next: Caching 101 — Memory Offloading and Latency Reduction
Series: Caching
- Caching 101 — Memory Offloading and Latency Reduction
- Caching Strategies — Aside, Through, Behind, and Refresh-Ahead
- Cache Eviction Policies — LRU, LFU, TTL, and Friends
- Distributed Caching — Sharding and High-Availability Clusters
- Cache Stampede — When Expiry Melts the Database (this guide)
- Stale Cache After Write — When Your Own Update Disappears
- Content Delivery Networks (CDN) — Edge Acceleration and Caching
- Bloom Filters — Probabilistic Set Membership at Scale
By Shubham Jain