ScalingExpert

How do you invalidate a cache?

“Design the invalidation strategy for a product catalogue cache in front of Postgres. Cover TTL, explicit invalidation, stampedes and what "stale" is allowed to mean.”

What this tests

  • Choosing between TTL, write-through, event-driven invalidation by staleness tolerance
  • Cache stampede: locks, early recompute, jitter
  • Consistency edge cases: race between DB write and cache set, delete-then-read
  • Negative caching and hot keys

Answers by level

Read the beginner answer first and notice what is missing.

Start from the staleness budget. If marketing tolerates a price change appearing within a minute, TTL = 60 s with cache-aside is enough and simple. If a price must never be stale, the write path invalidates: update Postgres, then delete the cache key; the next read repopulates. Delete rather than set on write, because a set can race with a concurrent read that populates an older value. Keep a TTL anyway as a safety net for missed invalidations.

Stampedes: when a popular key expires, hundreds of requests miss simultaneously and all hit Postgres. Mitigations: a short lock so one request recomputes and the rest wait or serve the stale value; probabilistic early recompute so the key refreshes shortly before expiry; TTL jitter so keys created together do not expire together — the midnight expiry of every key set at midnight is the classic outage. Negative caching (cache "not found" briefly) stops a missing product id from hammering the database.

Hot keys: a single product on the homepage can saturate one Redis shard; an in-process cache with a few seconds TTL in front of Redis handles that, at the cost of per-instance staleness.

Green flags · Red flags

Strong green flag · Includes every response-shaping dimension in the cache key so invalidation cannot miss a variant.
Green flags
  • Starts from a staleness budget, ideally per field group
  • Delete-on-write with a safety TTL, and knows why delete beats set
  • Names stampede defences: lock, early recompute, TTL jitter
  • Mentions negative caching and hot keys
  • Aware of the read-then-stale-set race and CDC as a fix
Red flags
  • "Just set a TTL and forget it."
  • Sets the cache on write and does not see the race
  • Gives every key the same TTL at the same time
  • Cannot explain what happens when a hot key expires under load

Follow-up questions

F1
At 00:00 the database CPU spikes to 100% every night. Why?
F2
A price update is not visible for 5 minutes despite delete-on-write. Suspects?
F3
How do you cache "product not found"?

Scenario

A catalogue cache uses a global 10-minute TTL. Support tickets say prices are wrong after a change, and the nightly reindex causes a five-minute Postgres overload when the cache is cold. Design the new policy: which keys, which TTLs, which invalidation triggers, and what happens during the reindex.

Learn this topic