Hot Key Cache Eviction
partialSummary
When Redis evicts a heavily-accessed cache key due to memory pressure under the allkeys-lru eviction policy, all concurrent requests for that key simultaneously miss the cache and issue identical queries to the backing database. Unlike TTL-based thundering herd, this eviction is triggered by memory pressure rather than expiry : meaning it can affect recently-accessed keys and occurs unpredictably as memory utilization crosses eviction thresholds, not at a predictable scheduled time.
Description
Redis allkeys-lru eviction works by maintaining an approximation of recently-used order and evicting the least-recently-used keys when memory reaches maxmemory. The LRU approximation (configurable via maxmemory-samples, default 5) randomly samples N keys and evicts the least-recently-used among them. This means a hot key can be evicted if it is not among the N sampled candidates: the probability increases as the hot key pool grows relative to the total key count.
The dangerous scenario: a hot key serving 500 requests/second is cached alongside 100,000 other keys. Memory pressure forces eviction. Redis samples 5 keys; the hot key is not among them. A moderately warm key is evicted. 10 ms later, memory pressure is still present; the hot key IS sampled and is the least-recently-used among its sample (because the sample included even hotter keys). The hot key is evicted. All 500 in-flight requests for it simultaneously miss the cache and query the database. This looks identical to thundering herd from the database perspective, but the eviction is silent: no TTL countdown, no scheduled expiry, no operator-predictable timing.
The failure is self-amplifying through a feedback loop. The hot key eviction causes a database load spike. The database query latency increases. Cache repopulation is delayed because the query takes longer. During this extended miss window (2-10x longer than normal query time), more cache misses accumulate. Each miss attempts another query. The database connection pool begins to queue. Queue depth grows. Timeout errors begin. In systems with circuit breakers, the circuit may open, blocking all requests to the backend for the entire circuit recovery window.
The problem is specific to allkeys-lru and allkeys-lfu policies, which can evict any key. Systems using volatile-lru (only evict keys with TTL set) are immune to hot key eviction on keys without a TTL. However, many production deployments use allkeys-lru to handle cases where applications set keys without TTLs, trading eviction safety for operational simplicity.
Characteristics
Triggers
- ·Redis memory utilization exceeds maxmemory threshold, triggering eviction
- ·Sudden traffic spike increases total key footprint (new users, new feature launch) until memory saturates
- ·Large value keys inserted that consume a disproportionate share of memory, forcing aggressive eviction of small hot keys
- ·maxmemory-samples set to 5 (default), making LRU approximation coarse enough to occasionally evict hot keys
Detection Signals
Mitigation Strategies
Switch Redis eviction policy to volatile-lru and ensure that hot keys are NOT given a TTL. Keys without a TTL are never evicted under volatile-lru (only keys with TTL are candidates for eviction). Hot keys that must not be evicted are set with SET key value (no EX/PX). This requires discipline in application code to distinguish hot durable keys from warm expendable keys, but completely prevents hot key eviction.
On a cache miss for any key serving >50 req/s, acquire a short-lived Redis lock (SETNX hot_key_lock 1 PX 5000) before querying the database. Only the lock holder executes the database query and repopulates the cache. All other concurrent misses for the same key poll the lock and wait. This limits N simultaneous database queries to 1, regardless of whether the miss was caused by eviction or TTL expiry. Reduces stampede impact by 99% for hot keys.
Increase maxmemory-samples from 5 to 10 or 20. Higher sample counts make the LRU approximation more accurate, significantly reducing the probability that a recently-accessed hot key is incorrectly selected for eviction. At maxmemory-samples=10, eviction quality approaches true LRU. The CPU cost increase is less than 10% on typical workloads. This does not prevent eviction under extreme memory pressure but reduces the probability of hot key eviction substantially.
Recovery Steps
- 1.Check Redis keyspace_misses in INFO stats: a sudden increase confirms a cache miss event
- 2.Identify the evicted key by correlating database slow query log with the cache miss timestamp
- 3.Manually re-populate the evicted key by running the backing query once and setting the result in Redis
- 4.If database is under stampede load, execute pg_terminate_backend for duplicate inflight queries before repopulating
- 5.After recovery, monitor Redis memory utilization: if consistently >90%, either increase Redis maxmemory or reduce the cache key footprint
Estimated recovery time: 30–90 seconds after manual cache repopulation. Database load normalizes within 30 seconds of the hot key being restored. If connection pool was exhausted, allow an additional 30–60 seconds for the pool to drain queued requests.
Affected Systems
Patterns
Technologies
Basis
Redis LRU eviction mechanics are precisely documented in Redis source code and official documentation; maxmemory-samples behavior is empirically verified; the hot key eviction pattern is a known production failure mode distinct from TTL-based thundering herd