Keeping a cache consistent with the database

Caching and Redis Senior Python 3.13+ PostgreSQL 17+ Reviewed By Best Latest Apps

Order the steps

Order the race that leaves a stale value in the cache.

  • Writer deletes the cache key
  • Writer commits the new row
  • Reader misses the cache and reads the old row
  • Reader stores its old value in the cache

Choose an answer, then open Show answer below to check it.

Show answer

Answer: C B A D

  1. Reader misses the cache and reads the old row It now holds the old value in memory.
  2. Writer commits the new row Database is updated.
  3. Writer deletes the cache key The cache is empty.
  4. Reader stores its old value in the cache Stale until the TTL expires.

30-second answer

Common causes: the cache was updated before the database transaction committed (and then it rolled back), or a slow reader loaded the old row, the writer deleted the key, and the reader then stored its stale copy. Fixes: delete the key after commit, keep TTLs short enough to bound staleness, and for stricter needs delete again shortly after (delayed double delete) or drive invalidation from the database's change stream so every writer is covered.

Practise saying it · 35 s. No recording, just a timer

How do you keep a cache consistent?

Say your answer out loud, then check which of these points you covered:

  • Delete after commit
  • Reader/writer race
  • Short TTLs bound staleness
  • Versioned sets or double delete
  • CDC for all writers

Deep dive

Versioned values: store the row's version with the value and refuse to SET an older version (a Lua script compares).

Change data capture (Debezium reading WAL) catches writes from every service and script, not just your app.

Some data can't be stale at all (balances); read it from the database.

Key naming conventions make bulk invalidation possible (tenant:7:* via a tag set, not KEYS).

Common mistakes

  • Invalidating inside the transaction before COMMIT.
  • Relying on application-level invalidation when other services write the same tables.
  • Running KEYS * in production to find keys to delete.

Senior take & follow-ups

Explain the two races, delete-after-commit, TTLs, and CDC for completeness.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why is KEYS dangerous?

    Show hint

    It scans the whole keyspace in one blocking call; use SCAN or maintain index sets.

  2. What's the delayed double delete?

    Show hint

    Delete after commit, then again after a short delay to clear a racing stale fill.

Suggest a fix if something here is wrong or out of date.