Caching Patterns

Knowing to cache is one thing; wiring the cache into your application correctly is another. Should the application manage the cache itself, or should the cache sit transparently in front of the source? Should writes go to the cache, the database, or both — and in what order? These questions have standard answers — the caching patterns — and choosing the right one shapes your consistency, performance, and complexity. Getting the pattern right is how caching goes from "store some stuff" to a coherent, correct design.

Caching patterns are the standard ways applications interact with a cache — how reads and writes flow between the application, the cache, and the source. This post covers the main read patterns (cache-aside, read-through) and write patterns (write-through, write-back, write-around), their tradeoffs, and how to choose. These patterns structure the read/write flow around a cache, building on the fundamentals (hits/misses) and invalidation (consistency) from earlier posts.

Cache-aside (lazy loading)

The most common caching pattern is cache-aside (also “lazy loading”) — the application manages the cache explicitly, loading data into it on misses:

   Cache-aside read:
     app checks cache → HIT: use cached value
                      → MISS: app fetches from source → app stores in cache → use

Cache-aside (lazy loading) — the application explicitly checks the cache, and on a miss fetches from the source and populates the cache — is the most common caching pattern: simple, resilient (cache-optional), and efficient (caches only used data), at the cost of app-side caching logic and first-access misses. A related pattern moves that logic into the cache itself.

Read-through and write patterns

Beyond cache-aside, other patterns move caching logic into the cache layer or define how writes flow. The main ones:

Read-through (the cache loads on miss, transparent to the app) and the write patterns — write-through (write cache+source together — consistent but slower writes), write-back (write cache first, source async — fast writes but loss risk), and write-around (write to source, bypass cache — avoids caching unread writes) — structure how reads and writes flow around the cache. Each makes different consistency/performance tradeoffs.

Understanding the tradeoffs

The patterns differ along a few key dimensions — understanding these tradeoffs is how you reason about them:

The patterns’ tradeoffs turn on who manages the cache (app vs cache layer), consistency vs write performance (the write patterns’ spectrum), and what gets cached (lazy vs eager, whether writes populate). Understanding these axes lets you reason about which pattern fits — rather than memorizing patterns, understand the tradeoffs they make. Then choosing follows from the workload.

Choosing a pattern

Selecting caching patterns depends on the read/write workload and consistency needs — practical guidance:

Caching patterns — cache-aside (the common default: app-managed, lazy, resilient), read-through (cache-managed loading), and the write patterns write-through (consistent), write-back (fast writes), and write-around (bypass cache on write) — structure read/write flow around a cache with different consistency/performance/complexity tradeoffs, chosen by workload. Next: distributed caching — caching across multiple machines (Redis, Memcached).

Key takeaways

Further reading

Sources & References

Cache-aside, write-through, and more