The Contract
TTL = maximum age a cached copy may reach before it's
considered dead and dropped.
SET user:912 = {...} EX 300 ← lives at most 300 seconds
guarantees delivered:
- staleness is BOUNDED (≤ TTL + fetch time)
- memory self-cleans (expired keys leave)
- invalidation bugs have a deadline (worst case = TTL)
TTL is the safety net under EVERY pattern:
even cache-aside's race conditions and missed invalidations
heal themselves when the clock runs out.
Choosing Values
| Data class | Typical TTL | Reasoning |
|---|---|---|
| Static assets | 31536000 (1yr) | Content-hashed; never stale |
| Product catalog | 300–3600s | Changes hourly-ish, tolerance high |
| User profiles | 60–600s | Edits visible within a minute or two |
| Session data | session length | Security-bound |
| Auth decisions | 5–60s | Balance security vs load |
| Rate counters | window size | Semantics, not freshness |
derive from the QUESTION: "how stale may this be before
someone complains or something breaks?" that number IS your TTL.
not rounder than needed, not tighter than needed.
Expiry Mechanics
stores don't clock-watch every key:
REDIS approach:
- LAZY: key checked on access; expired → treated as missing
- ACTIVE: background loop samples keys with TTL,
evicts expired ones proactively (bounds memory growth)
consequences:
- never-accessed expired keys linger briefly until active cycle
- TTL resolution/accuracy is approximate — don't build
correctness on millisecond expiry precision
TTL Interactions and Traps
REFRESH ON READ?
- cache-aside usually sets fresh TTL on refill (fixed age per fill)
- sliding expiration (reset TTL every hit) suits sessions;
wrong for freshness-bound data (hot key NEVER expires → stale forever)
JITTER:
mass-set keys with same TTL → synchronized stampede at expiry
ttl = base ± random jitter ← cheap fix, own lesson later
TTL=0 / NO TTL:
- permanent keys are a memory leak with extra steps;
audit for them; locks/sessions especially need explicit lives
Staleness Math
worst-case staleness chain for cache-aside:
write at T0 → delete cache → miss → refill with FRESH value ✓
BUT if delete fails/misses: old copy serves until TTL dies
so effective consistency contract =
"reads see writes within TTL" (plus failure modes)
state this in design docs. "TTL 300s bounds staleness"
is a real engineering statement auditors can hold you to.
Interview Framing
Every cache answer should carry TTLs attached to entity classes (“profiles 120s, catalog 30m”). Scored extras: lazy+active expiry mechanics, refresh-on-read trap (“sliding TTL makes hot keys immortal”), jitter mention. The one-liner that lands: “TTL is the bound that makes every other invalidation mistake survivable.”
Premium Content
Unlock TTL and all premium lessons with a subscription.
All premium lessons
Ad-free experience
Priority support
From ₹199.99/year — See plans