# Caching patterns

> Cache-aside, read-through, write-through and write-behind, side by side.

Concept · Caching · https://levelcode.org/concepts/caching-patterns

Four standard ways to put a cache in the data path. They differ in who loads the cache and when writes reach the database.

| Pattern | Reads | Writes | Strength | Weakness |
|---|---|---|---|---|
| Cache-aside (lazy loading) | App checks cache; on a miss, reads the DB and fills the cache | App writes the DB, then deletes the cache key | Caches only what's read; cache outage = slower, not broken | Stale-set race; first read after a change is a miss |
| Read-through | The cache (or a library) loads from the DB on a miss | Usually combined with write-through or cache-aside writes | Simpler application code | Same staleness questions; needs a smart cache layer |
| Write-through | Reads hit a warm cache | Each write goes to cache and DB together | Recently written data is always cached | Slower writes; caches data that may never be read |
| Write-behind (write-back) | Reads hit the cache | Write to cache, acknowledge, flush to DB later in batches | Absorbs very high write rates | Data not yet flushed is lost if the cache fails |

## Picking one

- **Cache-aside** is the default for application data: product pages, profiles, configuration. The Backend with Go roadmap's Redis lesson implements it.
- **Write-through** fits data that's read right after it's written (a user's session or settings).
- **Write-behind** fits counters and metrics — view counts, likes, rate-limit tallies — where losing a few seconds of updates is acceptable and per-write database updates would be expensive.
- **Refresh-ahead** (a variant) reloads popular keys before they expire, avoiding misses on hot data entirely; see [cache stampedes](https://levelcode.org/concepts/cache-stampede).

## Rules that apply to all of them

- Every entry has a TTL: the bound on how long a missed invalidation can serve wrong data ([cache invalidation](https://levelcode.org/concepts/cache-invalidation)).
- The cache is an optimisation unless you've deliberately made it a store (write-behind): the database remains the source of truth, and the system must survive an empty cache.
- Configure an eviction policy for when memory fills ([eviction policies](https://levelcode.org/concepts/cache-eviction)).
