Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
YouTube Security VideosAndroid Police: Samsung is smashing records! #shorts #tech #phones(21.09.2026 um 13:55 Uhr)
YouTube Security Videosheise & c't: Bundesnetzagentur wollte diesen Futterautomaten verbieten(21.09.2026 um 13:53 Uhr)
YouTube Security VideosNeil Patel: Your Google Traffic Isn't An Asset It's A Loan #shorts(21.09.2026 um 14:05 Uhr)
Windows Tipps & SecurityF-14 A Tomcat Top Gun endlich als Revell Klemmbausteinmodell erhältlich(21.09.2026 um 14:27 Uhr)
Sichere ProgrammierungShow the Hand-Back Sample Before Approving an Agent Score(21.09.2026 um 14:15 Uhr)
Sichere ProgrammierungHybrid retrieval in one Postgres query: RRF over tsvector + pgvector(21.09.2026 um 14:15 Uhr)
YouTube Security VideosAndroid Police: Samsung is smashing records! #shorts #tech #phones(21.09.2026 um 13:55 Uhr)
YouTube Security Videosheise & c't: Bundesnetzagentur wollte diesen Futterautomaten verbieten(21.09.2026 um 13:53 Uhr)
YouTube Security VideosNeil Patel: Your Google Traffic Isn't An Asset It's A Loan #shorts(21.09.2026 um 14:05 Uhr)
Windows Tipps & SecurityF-14 A Tomcat Top Gun endlich als Revell Klemmbausteinmodell erhältlich(21.09.2026 um 14:27 Uhr)
Sichere ProgrammierungShow the Hand-Back Sample Before Approving an Agent Score(21.09.2026 um 14:15 Uhr)
Sichere ProgrammierungHybrid retrieval in one Postgres query: RRF over tsvector + pgvector(21.09.2026 um 14:15 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

The Thundering Herd Problem (Cache Stampede) — and How to Tame It

1. What Is the Thundering Herd Problem? The thundering herd problem (also called a cache stampede or dogpile effect) happens when a popular cache key expires or is missing, and a large number of concurrent requests all miss the cache at…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




1. What Is the Thundering Herd Problem?



The thundering herd problem (also called a cache stampede or dogpile effect) happens when a popular cache key expires or is missing, and a large number of concurrent requests all miss the cache at the same instant. Instead of one request hitting the database, hundreds or thousands do — simultaneously.



Picture a hot product page on an e-commerce site. The cache entry for product:12345 expires at exactly midnight. If that product gets 2,000 requests/second, all 2,000 requests in that window see a cache miss and stampede toward the database at once. The DB, which was only ever meant to serve the occasional cache-refill query, gets hammered with duplicate work — often enough to tip over under load, which then causes more timeouts, more retries, and a feedback loop that can take down the whole service.



The core issue isn't that the cache missed — misses are normal. The issue is redundant, uncoordinated work: every request tries to regenerate the same value independently, when only one regeneration was ever necessary.






2. The Solution Strategy: Locking (a.k.a. "Cache Mutex" / Request Coalescing)



The code below solves this with a distributed lock pattern built on Redis's SETNX (set-if-not-exists). The idea:




On a cache miss, only the first goroutine to notice gets to regenerate the value. Everyone else waits for that one regeneration to finish, then reads the freshly-populated cache.




This turns an N-way stampede into effectively one database query, no matter how many concurrent requests miss at once.






3. Walking Through the Code



Step 1 — Try the cache first. This is the fast path. Most requests, most of the time, exit right here. No locking overhead is paid unless there's actually a miss. Notice the key cache:product:<id> as there is another key for lock `lock:product:, as the cache key will delete once expires.



func getProduct(id string) (Product, error) {

val, err := redis.Get(ctx, "cache:product:"+id)

if err == nil {

return val, nil // cache hit, done

}

}



Step 2 — Race for the lock. SETNX is atomic in Redis: only one caller among all the concurrent racers will get acquired == true. That caller becomes the designated "regenerator":




  • It queries the DB (the expensive operation).

  • It repopulates the cache with a fresh TTL (300*time.Second).

  • It deletes the lock, signaling "I'm done, cache is fresh."



go

acquired, _ := redis.SetNX(ctx, "lock:product:"+id, "1", 5*time.Second)

if acquired {

val := fetchFromDB(id)

redis.Set(ctx, "cache:product:"+id, val, 300*time.Second)

redis.Del(ctx, "lock:product:"+id)

return val, nil

}



The lock itself has its own TTL (5*time.Second). This is a safety net: if the regenerating goroutine crashes, panics, or the process dies before it can Del the lock, the lock self-expires instead of being held forever — preventing a permanent deadlock where nobody can ever regenerate that key again.



Step 3 — Everyone else waits and polls. All the losing goroutines (those that didn't get the lock) don't go to the DB themselves. Instead they poll the cache a handful of times with a short sleep in between, waiting for the winner to finish and populate cache:product:*. As soon as they see the key exists, they return it — they get a fresh value without ever touching the database.



go

for i := 0; i < 5; i++ {

time.Sleep(50 * time.Millisecond)

val, err := redis.Get(ctx, "cache:product:"+id)

if err == nil {

return val, nil

}

}



Step 4 — Bounded fallback. If the winner is unusually slow (5 × 50ms = 250ms of waiting with no result), the losers give up polling and fetch from the DB directly. This is a deliberate trade-off: it sacrifices some stampede protection in the worst case in exchange for bounded latency — no request waits forever, no matter what happens to the winner.



go

return fetchFromDB(id), nil

}






4. Why This Works
























Without locking With locking
N concurrent misses → N DB queries N concurrent misses → 1 DB query + (N-1) cache reads
DB load scales with traffic spikes DB load stays flat regardless of concurrency
Cache expiry moments are dangerous Cache expiry moments are absorbed by the lock


The lock converts a thundering herd into a queue of one worker, many waiters — a classic instance of the broader technique known as request coalescing or singleflight (Go's golang.org/x/sync/singleflight package implements the same idea in-process, without Redis, for a single-node case).






5. Trade-offs and Failure Modes to Be Aware Of





  1. Polling adds latency for losers. In the worst case, a loser waits up to 250ms before falling back to the DB itself. If your DB call is itself slow, tune the sleep/retry count accordingly, or switch to a pub/sub notification instead of polling (Redis Pub/Sub or a condition-variable-like mechanism) so losers are woken up immediately rather than polling blindly.


  2. Lock TTL vs. DB latency. If fetchFromDB can legitimately take longer than 5 seconds, the lock could expire while the winner is still working, letting a second goroutine "acquire" the lock and duplicate the fetch. Size the lock TTL comfortably above your p99 DB latency.


  3. Fallback defeats the purpose under sustained slow DB. If the DB is consistently slow (not just a one-off), many losers will time out their poll loop and hit the DB anyway, partially reintroducing the herd. This pattern protects best against short stampedes (cache expiry moments), not sustained DB degradation.


  4. Stale reads during regeneration. Everyone except the winner is blocked or reading old-then-new data; if you need to avoid ever serving a stale value while it's mid-regeneration, this pattern needs pairing with logic that serves the old value during the lock window (stale-while-revalidate) rather than making losers wait.






6. Related/Alternative Strategies





  • Probabilistic early expiration (XFetch): recompute the value slightly before it actually expires, with a probability that increases as expiry nears — spreads regeneration out over time instead of concentrating it at a single instant.


  • Stale-while-revalidate: serve the old (slightly stale) value immediately while one background goroutine refreshes it, so no request ever blocks.


  • In-process singleflight + distributed lock combo: dedupe requests within a single node using singleflight first (cheap, no Redis round-trip), and only use the Redis lock across nodes — reduces Redis load further in high-QPS services.



The pattern in your snippet — SETNX lock + bounded poll + DB fallback — is a solid, production-common baseline. The main dial to tune is the poll interval/count vs. lock TTL vs. your DB's actual latency profile.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten The Thundering Herd Problem (Cache Stampede) — and How to Tame It

Thematisch verwandte Begriffe: Thundering, Herd, Problem, Cache · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94097 | A vulnerability was determined in Netcore NBR200V2 1.3.241127.071246. Th…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick