.NET › Caching (In-Memory, Distributed & Redis)
What is the 'cache stampede' (thundering herd) problem, and how can you mitigate it?
AdvancedAnswer
A cache stampede occurs when a popular cache entry expires and many concurrent requests simultaneously discover the cache miss, all racing to recompute and repopulate the same expensive value at once, overwhelming the backing data source. Mitigations include: using a lock/semaphore per cache key to ensure only one request recomputes while others wait, using GetOrCreateAsync's built-in coordination (IMemoryCache handles this internally for the same key), or proactively refreshing cache entries before they fully expire.
private static readonly SemaphoreSlim _lock = new(1, 1);
public async Task<Product> GetProductAsync(int id) {
if (_cache.TryGetValue($"product-{id}", out Product cached)) return cached;
await _lock.WaitAsync();
try {
if (_cache.TryGetValue($"product-{id}", out cached)) return cached; // double-check
var product = await _repository.GetByIdAsync(id);
_cache.Set($"product-{id}", product, TimeSpan.FromMinutes(10));
return product;
} finally { _lock.Release(); }
}Real-world example A viral news article's cache entry expiring under heavy simultaneous traffic previously caused 500 concurrent database queries for the same article; adding a per-key lock reduces this to exactly one database query while the other 499 requests wait briefly for the now-cached result.