Stampede Protection | @express-route-cache
How two-tier request coalescing prevents the thundering herd problem from crashing your database.
Stampede Protection
A "Cache Stampede" (also known as the "Thundering Herd" problem) occurs when a popular cache entry expires and hundreds of concurrent requests hit your database simultaneously to refresh it.
Two-Tier Request Coalescing
@express-route-cache prevents this with a two-tier coalescing system that works both per-process and across distributed servers.
Tier 1: Distributed Lock (Redis / Memcached)
When your adapter implements the optional setNX method (both the Redis and Memcached adapters do), the library elects a single leader server across your entire cluster:
- First server to receive a cold-cache request calls
setNXto acquire a distributed lock. - All other servers detect the lock is held and poll the cache store at 150ms intervals (up to 10 attempts ≈ 1.5s) waiting for the leader to populate the entry.
- Once populated, the followers read the fresh entry from the cache and serve it — no extra DB queries.
- If the leader fails or polling times out, the follower falls through to run the handler itself as a safety valve.
Lock TTL & Crash Recovery
The stampede lock TTL is set to staleTime + gcTime + 30 seconds. For example, with staleTime: 60, gcTime: 300, the lock lives for 390 seconds in Redis.
This means:
- If the leader completes normally, it explicitly deletes the lock key so followers can proceed immediately.
- If the leader crashes before populating the cache, followers poll for up to ~1.5s then fall through and run the handler themselves — guaranteeing eventual response at the cost of one extra handler execution per follower.
- The long TTL is a safety net to prevent the lock from lingering indefinitely after an unexpected process exit.
Tier 2: Local In-Process Lock (all adapters)
Within a single Node.js process, an LRU map (inflightRequests) coalesces concurrent requests for the same key:
- First request hits a cache MISS. It starts executing the Express handler and stores a Promise in the in-process map.
- Subsequent requests for the same key await the existing Promise instead of starting a new handler execution.
- Completion: Once the first request finishes, all waiting requests resolve with the same cached entry simultaneously.
Configuration
Stampede protection is enabled by default. You can toggle it if needed:
const cache = createCache({
stampede: true, // Default
});[!NOTE] Tier 1 (distributed locking) activates automatically when your adapter implements
setNX(Redis, Memcached). For the Memory adapter, only Tier 2 (in-process) protection is active.
O(1) Epoch Cache Invalidation | @express-route-cache
How express-route-cache achieves O(1) cache invalidation using Epoch Versioning — no Redis SCAN, no KEYS command. Instantly invalidate any route pattern in production.
Standalone Fetch | @express-route-cache
Use cache.fetch() for manual data caching with SWR, Stampede Protection, and exponential backoff retries — not just for Express routes.