1. Why Cache Write Strategy Matters

Adding a cache is straightforward for reads: check the cache, fall back to the database on a miss. Writes are more complex because you now have two places data could live — the cache and the database — and they can diverge. The write strategy defines exactly how and when writes propagate between the two, balancing three competing concerns:

  • Consistency: Is the cache always in sync with the database?
  • Write latency: How long does a write operation take?
  • Durability: Is data safe if the cache crashes?

2. Cache-Aside (Lazy Loading)

Cache-aside is the most widely used pattern in web applications. The application code is responsible for managing the cache — the cache does not communicate with the database on its own.

  READ PATH (Cache-Aside):
  App → Cache: GET user:123
       Cache HIT  →  return data to App
       Cache MISS →  App fetches from DB
                  →  App writes to Cache (SET user:123 ttl=300)
                  →  return data to App

  WRITE PATH (Cache-Aside):
  App → DB: UPDATE users SET name='Alice' WHERE id=123
       DB write succeeds
  App → Cache: DEL user:123   (invalidate stale entry)
       Next read will repopulate cache from DB

The most common invalidation approach is delete on write: when data changes, delete the cache key. The next read will be a miss and will load fresh data from the database. This avoids stale reads at the cost of one extra cache miss per write.

Cache-Aside in Redis — Python Example

Use redis.get(key) on read; if None, fetch from DB and redis.setex(key, ttl, value). On write: update DB first, then redis.delete(key). Always update the DB before deleting from cache — if the cache delete fails, the TTL will eventually expire the stale entry.

3. Write-Through Cache

In write-through, every write goes to the cache and the database simultaneously. The write operation is not considered complete until both have been updated. The cache is always in sync with the database — there is no stale data.

  WRITE-THROUGH FLOW:
  App → Cache Layer: write(key, value)
        │
        ├──▶  Cache: SET key value        (synchronous)
        │
        └──▶  Database: UPDATE/INSERT     (synchronous)
                   │
                   Both must succeed ──▶  return success to App

  READ FLOW (always a cache hit after first write):
  App → Cache: GET key  →  HIT (data always present)

Write-through is ideal for read-heavy workloads where data must never be stale. The downside is write latency — you pay the database write cost on every operation, even for data that is never read again. This also means the cache fills up with data that may never be accessed, wasting memory.

4. Write-Back (Write-Behind) Cache

Write-back optimises for write performance by decoupling the cache write from the database write. The application writes only to the cache, and a background process asynchronously flushes dirty data to the database.

  WRITE-BACK FLOW:
  App → Cache: SET key value (dirty=true)   ← fast, synchronous
        │
        └──▶  return success to App immediately

  Background Flusher (async):
        │
        ├── every N seconds OR when cache is full:
        ├── find all entries where dirty=true
        ├── write to Database
        └── set dirty=false on success

  RISK: If cache crashes before flush:
        dirty entries are LOST (never reached DB)

Write-back is used in CPU L1/L2 caches, where the performance gain from not writing to RAM on every cache line update is enormous. It is also used in some database buffer pools (MySQL InnoDB dirty pages) and write-heavy NoSQL use cases. The dirty flag bit tracks which entries need to be flushed.

Write-Back Data Loss Risk

If a Redis node with write-back dirty data crashes before the async flush completes, those writes are permanently lost. Only use write-back where some data loss is acceptable (e.g. analytics counters, session data) or where you have strong cache persistence (Redis AOF with fsync every write). For financial or transactional data, use write-through instead.

5. Read-Through Cache

Read-through is a variant of cache-aside where the cache layer itself fetches from the database on a miss, rather than the application doing it. The application only ever talks to the cache.

  • Application calls cache.get(key)
  • On a hit: cache returns the value directly
  • On a miss: the cache fetches from DB, stores the result, and returns it
  • Application code does not contain any DB fallback logic

Read-through simplifies application code but requires the cache to understand the data model. AWS DynamoDB Accelerator (DAX) is a managed read-through/write-through cache for DynamoDB. Hibernate's second-level cache is another example.

6. Strategy Comparison

StrategyWho manages cache?Write latencyStale data riskData loss riskBest for
Cache-AsideApplicationLow (write to DB only)Low (invalidate on write)NoneGeneral-purpose, most web apps
Write-ThroughCache layerHigh (write to cache + DB)NoneNoneRead-heavy, consistency-critical
Write-BackCache layerVery low (cache only)None (after flush)High (pre-flush crash)Write-heavy, loss-tolerant
Read-ThroughCache layerLow (write to DB only)Low (with invalidation)NoneSimplifying application code

7. Real-World Examples by Strategy

Cache-Aside — Redis in Web Applications

The vast majority of web applications using Redis follow cache-aside. The application checks Redis on every read and manages cache invalidation on writes. Redis's rich data structures (strings, hashes, sets) make it easy to cache complex objects. A typical pattern: cache user sessions, product listings, and computed results with TTLs of 5–60 minutes.

Write-Through — CDN Edge Caches

When you publish new content to a CDN (e.g. Cloudflare, CloudFront), the CDN pushes the content to edge nodes as part of the write operation. Every edge node receives the update synchronously — this is write-through at a global scale. The benefit: every user gets fresh content immediately after publication, with no cache-miss latency on the first request.

Write-Back — CPU L1/L2 Cache

Modern CPUs use write-back for their cache lines. When the CPU writes data, it goes to the L1 cache only (very fast). The cache line is marked dirty. It is flushed to L2, L3, or RAM later by the cache controller. This is why a sudden power loss can corrupt file system state — dirty cache lines in the CPU were never flushed to RAM (and then to disk). The OS uses fsync and write barriers to force dirty data through.

Write-Back — MySQL InnoDB Buffer Pool

InnoDB keeps modified (dirty) pages in its buffer pool and flushes them to disk asynchronously via the dirty page flusher thread. This is write-back caching at the database level. The redo log (WAL) provides durability — even if dirty pages are lost in a crash, they can be replayed from the redo log, giving write-back semantics with durability guarantees.

How We Research and Update This Guide

We test the underlying formula or workflow, compare outputs with reliable references, and revise examples whenever the page content changes.

  • The workflow or formula is tested directly in the tool and compared against independent reference examples.
  • Examples are kept practical so readers can verify the result without hidden assumptions.
  • Pages are revised whenever the interface, calculation flow, or surrounding guidance materially changes.

Frequently Asked Questions — Caching Strategies