Course contentsShow
← Databases & SQL
Lesson 1299 of 1,95312. Key-Value and Caching EnginesFree lesson

Handling Cache Stampedes

Implement locking or probabilistic recomputation to prevent database overload during cache misses.

In this lesson, you will learn how to prevent a "Cache Stampede"—a scenario where a surge of concurrent requests simultaneously triggers a database overload when a popular cache key expires.

The Anatomy of a Stampede

Imagine a high-traffic e-commerce site where the "Daily Deal" product info is cached. When that key expires, the first request sees a cache miss and queries the database. However, if your application is under high load, dozens of other requests might arrive milliseconds later, see the same miss, and all blast the database at once. This thundering herd can crash your database, even if the query is fast.

Solution 1: Distributed Locking

To prevent the herd, we use a distributed lock. When a request detects a cache miss, it attempts to acquire a lock (often using a Redis SET key value NX PX 5000 command). Only the thread that successfully acquires the lock is permitted to query the database and update the cache. All other threads wait or return a stale value until the lock is released.

# Pseudo-code for locking strategy
value = redis.get("daily_deal")
if value is None:
    if redis.set("lock:daily_deal", "1", nx=True, ex=5):
        # Only one process executes this
        value = db.query("SELECT * FROM deals WHERE id=1")
        redis.set("daily_deal", value, ex=3600)
        redis.delete("lock:daily_deal")
    else:
        # Others wait or serve slightly stale data
        value = get_stale_data()

Solution 2: Probabilistic Recomputation (XFetch)

Instead of hard locking, we can use probabilistic early expiration. Instead of waiting until the TTL is zero, each request calculates a probability of recomputing the cache before it expires. By randomly deciding to refresh the cache as the TTL approaches zero, we ensure that only one request hits the database while the rest continue to receive the existing cache value, effectively smoothing out the spike.

By shifting from "everyone refreshes at once" to "one person refreshes early," you keep your database load stable and your application performant.

Key Takeaway: To avoid cache stampedes, implement synchronization logic—such as distributed locks or probabilistic early recomputation—to ensure that only one request triggers a database fetch when a cache key expires.