Cache invalidation

Pause a reader between its database read and cache write

A controlled interleaving can reproduce stale repopulation reliably. Ordinary load tests often miss this short but important race.

In this article

Set up two versions of one record

Use a synthetic record whose value clearly identifies its revision. Start with revision 4 in the database and an empty cache. Arrange a test hook that pauses a reader after it loads the database value but before it populates the cache.

The pause must sit in the real cache loading path. Sleeping somewhere in the request handler without controlling the exact boundary makes the test timing unreliable.

Capture the loaded revision and the operation identity so the test can explain what happened rather than only report an unexpected final value.

Perform the update while the reader waits

Commit revision 5 through the normal writer and run its invalidation path. Confirm that the database now contains revision 5 and that the relevant cache entry has been removed or superseded.

Resume the paused reader. In a simple implementation, it may now store revision 4 after invalidation has finished. A subsequent request can receive the older value even though the writer followed a commit-then-delete sequence.

This is the behaviour under investigation. The test should not assume that one deletion establishes strong consistency.

Assert the chosen guarantee

If the design uses source revisions to reject older fills, verify that revision 4 cannot replace a known newer generation. Check how that knowledge survives eviction and process restarts.

If the design accepts bounded staleness, verify the actual upper bound and the operations that bypass the cache. Use a controlled clock where possible. A test that waits an approximate number of seconds can be slow and flaky without proving the exact policy.

Test invalidation failure separately. A network error during deletion should be observable, and the recovery path must match the promised freshness. An unobserved best-effort delete cannot support an immediate-consistency claim.

Expand to the visible read path

Repeat the exercise with any browser or edge layer involved. The backend may return revision 5 while a client still displays revision 4 from its own cache.

Finish by performing the business action that depends on the value. For example, a catalogue may show approximate availability while checkout correctly rechecks stock. The final assertion should distinguish an allowed stale display from an invalid committed action.

Keep the controlled interleaving as a regression test. It documents a specific concurrency failure far more clearly than a general instruction to invalidate caches carefully.

Primary sources

Microsoft: cache-aside pattern

References checked 11 September 2026.