Skip to content
Optimal Lab

System design · interactive

Cache invalidation

The app reads a price through a cache: on a miss it loads from the database and caches it for 60 s. At 15 s the price changes from 10 to 12. Which reads still see 10?

Reads every 10 s · write at 15 s

  1. 0 s10miss → DB
  2. 10 s10cache
  3. 20 s10cache
  4. 30 s10cache
  5. 40 s10cache
  6. 50 s10cache
  7. 60 s12miss → DB
  8. 70 s12cache
  9. 80 s12cache
  • 15 s: UPDATE price = 12 (cache untouched)

4 stale reads

The cache keeps serving the old price until the entry expires at 60 s: 4 stale reads.

On write

Step 1 of 4

  1. 1

    TTL bounds how stale

    Every entry expires eventually. Simple, but you accept stale data for up to the TTL.

    Always set one, even with other strategies.

  2. 2

    Delete on write

    After updating the database, delete the cache key. The next reader reloads it.

    Delete rather than set: it avoids writers racing each other.

  3. 3

    Races can put old data back

    A reader that loaded before the write can store its old value after your delete. Short TTLs, a second delayed delete, or versioned values limit the damage.

    Facebook's memcache paper uses leases for this.

  4. 4

    Write-through or change data capture

    Update the cache in the write path, or stream database changes (CDC) to invalidate keys.

    More moving parts, fresher reads.

In production

Tools and technologies

Every cache layer needs an invalidation story.

Not tied to one language — use these names when you search docs or design a system.