TTL Strategy¶
1. Decision¶
Implement explicit Time-To-Live (TTL) expiration policies on all cache keys as a secondary safety net against permanent data staleness, combining fixed TTLs, randomized jitter, and sliding windows based on volatility and business SLA requirements.
2. 30-Second Answer¶
Time-To-Live (TTL) defines the lifespan of a cached key before it is automatically evicted from memory by the caching engine (e.g., Redis EXPIRE). TTL acts as an essential safety net ensuring that missed or failed programmatic cache invalidations do not leave stale data in memory indefinitely. Selecting a TTL strategy requires balancing freshness against database load: short TTLs (seconds) guarantee tighter consistency but increase DB read queries; long TTLs (hours/days) maximize cache hit ratios but extend stale data windows. High-scale systems apply Randomized Jitter to TTLs to prevent Cache Avalanches, and use Sliding TTLs for active user sessions.
3. Decision Matrix¶
| Option | Best For | Avoid When | Latency | Scalability | Consistency | Operational Complexity |
|---|---|---|---|---|---|---|
| Fixed Short TTL (1s - 60s) | Frequently changing data, news feeds, live metrics, flash sale inventory | Low-traffic applications where DB queries are expensive | Low; Frequent DB read refreshes | High protection for DB | Stronger (Short staleness window) | Low |
| Fixed Long TTL (1h - 24h+) | Static reference data, country lists, historical report summaries | Frequently updated data without reliable active cache invalidation | Ultra-Low (High cache hit ratio) | High | Weaker (Long staleness window if invalidation fails) | Low |
| Randomized Jitter TTL (\(T \pm \Delta t\)) | Mass batch cache populating, scheduled cron jobs, catalog indexing | Workloads requiring deterministic simultaneous cache expiration | Low | Prevents Cache Avalanches | Predictable average staleness | Low |
| Sliding Window TTL | User authentication sessions, shopping carts, active connection state | Static reference data where idle keys should expire deterministically | Low | Extends session life on activity | Eventual | Medium |
4. Selection Rules¶
| Requirement | Best Choice | Rationale / Example |
|---|---|---|
| Prevent Simultaneous Cache Expiration | TTL + Random Jitter | Add \(\pm 10-20\%\) random jitter to base TTL to spread eviction spikes |
| Active User Session Management | Sliding TTL | Refresh key TTL (EXPIRE key 1800) on every user HTTP request |
| Volatile Real-Time Product Inventory | Short TTL (5s - 15s) | Limits overselling window if active invalidation fails |
| Static System Metadata & Config Flags | Long TTL (24h+) + Active Invalidation | Cache permanently; rely on active pub/sub invalidation when updated |
| Protect Database from Infinite Memory Growth | Default Mandatory TTL | Every key written to Redis MUST have a TTL to prevent RAM OOM |
| Probabilistic Early Expiration (XFetch) | Probabilistic Expiration | Asynchronously refresh key before TTL expires when read traffic is high |
5. Tradeoffs¶
- Short TTL vs Long TTL
- Gain (Short): Minimal window of stale data; automatically self-heals invalidation bugs.
- Lose (Short): Lower cache hit ratio; higher DB query load.
- Deterministic Expiration vs Randomized Jitter
- Gain (Jitter): Flattens database CPU spikes by preventing thousands of keys expiring at the exact same second.
- Lose (Jitter): Keys expire at non-deterministic timestamps, complicating test assertions.
- Sliding Window Refresh vs Fixed Lifespan
- Gain (Sliding): Active users stay logged in seamlessly without abrupt session drops.
- Lose (Sliding): Requires extra write operation (
EXPIREcommand) on every read, increasing Redis QPS load. - Active Cache Invalidation + TTL Safety Net
- Gain: Immediate data freshness on writes + guaranteed cleanup if invalidation logic fails.
- Lose: Dual overhead of writing programmatic invalidation triggers and tuning TTL values.
- Passive Eviction vs Active Eviction Memory Overhead
- Gain: Expired keys free RAM for new writes.
- Lose: Redis active expiration algorithm consumes minor background CPU sampling expired keys.
6. Interview Counter Questions¶
- What is a Cache Avalanche and how does TTL Jitter prevent it?
- How does Redis process key expiration internally (Passive vs Active Eviction)?
- What happens if Redis memory fills up before keys reach their configured TTL?
- How does Probabilistic Early Expiration (XFetch algorithm) prevent Cache Stampedes?
- Why is setting "No TTL" (persistent keys) a dangerous anti-pattern in Redis caching?
- How do you implement a Sliding Window TTL efficiently without doubling Redis command traffic?
- What is the impact of replica lag on key expiration in Redis primary-replica clusters?
- How do you choose the right TTL value for dynamic user-generated content vs static system configuration?
- Why shouldn't you rely only on TTL for cache invalidation in financial applications?
- What happens to key TTL during Redis
SETorRENAMEoperations?
7. Gold Standard Answers¶
- Cache Avalanche occurs when millions of keys are written with identical TTLs (e.g., midnight cron job), expiring simultaneously and dumping massive traffic on the DB. TTL Jitter adds random noise (
TTL = base + rand(0, 300s)), spreading DB load evenly over time. - Passive eviction: Expired key is deleted when a client attempts to read it. Active eviction: Redis runs a background task 10 times/sec sampling 20 random keys with TTLs, deleting expired ones. If \(>25\%\) are expired, it repeats.
- If memory reaches
maxmemory, Redis executes its configured eviction policy (e.g.,allkeys-lruorvolatile-lru), evicting unexpired keys based on access frequency/recency to make room for new writes. - XFetch computes a probability function based on read delta and remaining TTL: \(-\beta \cdot \log(\text{rand}())\). As TTL gets closer to 0, the probability of a read triggering an early asynchronous background DB refresh increases before the key actually expires.
- Without a TTL, keys missing explicit eviction logic accumulate infinitely in memory, leading to RAM exhaustion (
OOM), higher latency, and forced uncontrolled key evictions under load. - Combine read and expire commands into a single pipelined call or use Redis
GETEXcommand (GETEX key EX 1800), which returns the value and updates TTL in a single atomic network round-trip. - Replicas do not expire keys independently. When a key expires on the primary, the primary generates an explicit synthetic
DELcommand streamed to replicas in the WAL. - User-generated content (comments, profiles): Short TTL (1-5 mins) + Active Invalidation. Static system metadata (country codes, tax rates): Long TTL (24h+) + Event-driven Pub/Sub invalidation.
- TTLs leave a staleness window equal to the TTL duration. Financial systems require absolute consistency; relying solely on a 60-second TTL permits stale balance reads, risking double-spending.
- Executing a standard
SET key valuecommand overwrites and removes the existing TTL (key becomes persistent). UseSET key value KEEPTTLor explicitEXPIREto preserve TTL.
8. Common Mistakes¶
- Setting identical fixed TTLs on millions of keys created during batch jobs, triggering Cache Avalanches.
- Overwriting existing key TTLs accidentally by using standard
SETcommands withoutKEEPTTL. - Failing to set a default TTL on dynamic keys, causing Redis memory leaks.
- Depending on TTL as the sole mechanism for cache freshness in strict transactional domains.
- Issuing separate
GETthenEXPIREnetwork calls for sliding sessions instead of atomicGETEX.
9. Keywords¶
TTL, Time-To-Live, TTL Jitter, Cache Avalanche, Passive Eviction, Active Eviction, XFetch, Probabilistic Expiration, Sliding Window TTL, GETEX, KEEPTTL, maxmemory, Volatile-LRU.
10. Cheat Sheet¶
- Golden Rule: Always set a TTL on every cache key. No infinite persistent cache keys!
- Cache Avalanche Defense: Add Random Jitter (
base_ttl + random_offset) to spread key expiration over time. - Sliding Sessions: Use atomic
GETEX key EX 1800to read value and refresh TTL in 1 round-trip. - Redis Overwrites: Standard
SETclears key TTL. UseSET key val KEEPTTLto maintain existing TTL. - Early Refresh: Use XFetch algorithm to refresh hot keys asynchronously before TTL hits 0.
- Expiration Mechanism: Redis uses Passive (on read) + Active (background random sampling 10x/sec) eviction.