Skip to content
Back to all concepts
CachingArchitectureDesign Patterns

Caching Strategies

A breakdown of where to place your cache and how to keep it in sync with your database.

By ScaleWikiUpdated 3 min readIntermediate

Separate the source of truth from the fast copy

Caching strategy names describe who fetches data and when writes reach durable storage. They do not automatically provide a consistency level. Define the authoritative record, the acknowledgement point, and the response to each partial failure.

Cache-aside: simple reads, nontrivial races

The application checks the cache, reads the database on a miss and fills the cache. For a write, it commits the database change and invalidates the cached value. The cache-aside pattern documentation explains this arrangement and its consistency limits.

Consider this hypothetical schedule:

text
A: cache miss; starts reading database version 7
B: commits version 8; deletes the cache key
A: finishes its older read; stores version 7 in the cache
C: reads version 7 from the newly filled cache

Deleting after a write is not enough to prevent a delayed reader from repopulating old data. A short TTL bounds one kind of staleness but does not make the read linearizable. Version-aware fills, an ordered invalidation stream or bypassing the cache after a write can help under explicitly defined assumptions. Any comparison of versions and cache update must be atomic where the race occurs.

Read-through: move fetch logic into a component

A read-through adapter performs the miss lookup for the application. It can centralize request coalescing, timeout rules and metrics. This is an ownership distinction from cache-aside, not a guarantee that values remain fresh. The adapter still needs an invalidation strategy and a decision about unavailable origins.

Write-through: acknowledge after the intended writes

A write-through path synchronously updates the backing store through a cache layer. Specify the ordering and what happens if one write succeeds and the other fails. Two separate systems do not become one atomic transaction because a diagram places them in sequence.

Consider a write-through adapter that commits a profile update to the database, then times out while installing the new cache value. The authoritative update may be successful while the cache is stale. Define whether the caller receives committed success or an error requiring an idempotent retry, and how every reader avoids that stale entry until recovery. A flag held only in one process does not protect other readers. An integrated transactional cache may provide different guarantees; verify its documented scope.

Write-behind: the cache now holds pending work

Write-behind acknowledges before the backing database update finishes. If acknowledged writes exist only in volatile memory, a cache failure can lose them. A durable queue and replayable consumer can protect pending work, but then this is a replication pipeline with its own ordering, deduplication and monitoring responsibilities.

Batching counters may be useful when the product tolerates delayed totals. It is inappropriate to silently apply the same loss model to confirmed purchases. An acknowledgement should tell the caller exactly which durability promise was satisfied.

Worked decision: product description versus inventory

Suppose a product page is read 500 times/s while descriptions change once an hour. We allow descriptions to be up to 30 seconds old. Cache-aside with expiry can be a reasonable starting point, provided repeated failures cannot keep extending stale data indefinitely.

The buy button has a different invariant: stock cannot go negative. It sends a conditional update to the authoritative store even if the displayed quantity came from a cache. If the purchase succeeds but the response is lost, retry with the same operation identifier. Cache selection does not solve duplicate effects.

PatternQuestion to answer before use
Cache-asideCan an old fill race with invalidation?
Read-throughWho limits concurrent miss requests?
Write-throughWhat happens after only one store updates?
Write-behindWhich durable record survives acknowledgement?

Verify the contract

Test a crash between every two arrows in your write path. Replay invalidations out of order. Delay one old read until after a newer write, and compare the returned version. These experiments reveal more than labelling a pattern “high consistency.” Use caching overview and the capacity lab to account for normal misses and a cold cache.