Skip to main content

Reference: Cache Access and Invalidation Patterns

A short reference on read/write caching patterns and invalidation strategies — which to use when, and what breaks with each.

What it is

A cache is a fast, small store that sits between a client and a slower source of truth, holding recently- or frequently-accessed data. Useful caching requires picking two things: an access pattern (how reads and writes flow through the cache) and an invalidation strategy (when and how stale entries are removed).

When you care

Caching shows up in almost every system design interview. The trap is naming “we’ll use Redis” and moving on. Interviewers probe the access pattern (what happens on a miss, what happens on a write) and the invalidation story (how stale data is prevented or tolerated) — those are the decisions that actually shape correctness.

Read-side access patterns

PatternRead flowMiss handlingGood for
Cache-aside (lazy)App reads cache. On miss, app reads DB, writes cache, returns.App manages both stores.General-purpose reads; default choice.
Read-throughApp reads cache. On miss, cache reads DB, fills itself, returns.Cache library manages the DB hit.Uniform access path; offloads miss logic from app.
Refresh-aheadCache proactively refreshes entries before they expire.No miss if prediction is right.Predictable hot keys; latency-critical reads.

Cache-aside is the default. It’s explicit, easy to reason about, and survives a cache outage — the app falls back to the DB. The cost is duplicated logic at every call site.

Read-through collapses that duplication into the cache layer, which only helps if your cache library natively supports it. A cache outage here is harder to degrade gracefully around.

Refresh-ahead is a latency optimization layered on top of either, not a standalone pattern. Only valuable when you can predict hot keys and the DB read cost is high.

Write-side access patterns

PatternWrite flowConsistencyGood for
Write-throughApp writes cache, which writes DB synchronously.Cache and DB always match.Read-after-write consistency required.
Write-behind (write-back)App writes cache; cache writes DB asynchronously.Cache ahead of DB briefly; risk on crash.Write-heavy workloads where latency matters more than durability.
Write-aroundApp writes DB directly; cache is populated on read miss.Cache may lag DB on writes.Write-once-read-rarely data; avoids caching cold data.
Cache invalidation on writeApp writes DB, then deletes the cache key.Cache re-populated on next read.Most cache-aside systems. Simple and correct.

Write-through is the safest choice when reads must see writes immediately. Pays latency on every write.

Write-behind is fast but trades durability for throughput — if the cache dies before flushing, writes are lost. Rarely the right call outside specific high-write systems (counters, metrics, session data).

Write-around is the default pairing for cache-aside reads. Writes go to the DB; the cache fills naturally on the next read. A small variant — delete on write — explicitly invalidates the cache key on write and is the standard pattern for keeping cache-aside correct.

Invalidation strategies

StrategyMechanismTradeoff
TTL (time-to-live)Entry expires after N seconds.Simple; tolerates some staleness for a bounded window.
Explicit invalidationApp deletes the key on write.Correct but requires code at every write site.
Write-through / write-aroundCache is updated or invalidated synchronously with the DB write.Strongest consistency; highest write latency.
Pub/sub invalidationDB or service publishes a change event; cache nodes subscribe and invalidate.Works across cache clusters; adds infrastructure.
Version stampingEntries keyed by (id, version); new writes produce new keys, old keys age out.Avoids invalidation entirely; grows key space.

Eviction policies (when the cache is full)

PolicyRemovesGood for
LRU (least recently used)The entry unused for the longest.General-purpose; the default in most cache libraries.
LFU (least frequently used)The entry accessed the fewest times.Workloads with stable hot sets.
FIFOThe oldest entry by insertion time.Rarely the right choice; included for completeness.
TTL-onlyWhichever entry expired first.Time-bounded data (sessions, tokens).

Eviction and invalidation are different. Eviction runs when memory fills; invalidation runs when data changes. A cache can use both.

When to pick what

  • Default for general reads: cache-aside + delete-on-write + TTL backstop + LRU eviction.
  • Read-after-write required: write-through, or cache-aside with synchronous delete-on-write.
  • Write-heavy, durability-tolerant: write-behind.
  • Multi-node cache coherence: pub/sub invalidation on DB writes.
  • Immutable or append-only data (URL shortener codes, event logs): TTL alone is enough; the cache-invalidation problem doesn’t apply.

Cache invalidation is one of the two hard problems in computer science for a reason — the correct strategy depends on the read/write ratio, the consistency requirement, and whether stale data is tolerable. Name the choice and the tradeoff; don’t just name Redis.