Skip to content
Back to course
Lesson 6 of 23 · Extra

Cache Strategies: Cache-Aside vs Write-Through vs Write-Behind

Decision guide for picking the right cache-database coordination pattern: what you gain, what you lose, and why most systems use a hybrid.

intermediate8 min read3 diagramsUpdated 11 May 2026✓ Completed
On this page

TL;DR. Cache-aside is the right default for read-heavy workloads: the application owns the miss-and-populate logic, the database stays authoritative, and a cache outage degrades performance without losing data.1 Switch to write-through when read-your-writes is a product requirement (account balances, feature flags). Use write-behind only for reconstructable, high-throughput writes (counters, telemetry) where you accept a data-loss window equal to the flush interval.2 Most production systems combine all three, classified per field.

Learning Objectives

  • Compare cache-aside, write-through, and write-behind across consistency, latency, durability, and operational complexity.
  • Identify the workload characteristics (read:write ratio, staleness tolerance, durability needs) that determine which strategy wins.
  • Justify a hybrid approach that layers write-through onto cache-aside for critical fields.
  • Evaluate real-world systems (Facebook Memcache, TAO, Netflix EVCache) and explain why each chose its strategy.

The Core Trade-off

A cache strategy is a contract about which failure mode you pay for. The three dimensions that cannot all be optimized simultaneously are:

  1. Consistency between cache and database costs extra writes on the write path.
  2. Low miss latency costs memory and admission-policy complexity.
  3. Durability costs write throughput because every write must reach persistent storage before acknowledgment.12

Cache-aside optimizes the read path and accepts eventual consistency on writes. Write-through optimizes read-your-writes and accepts extra write latency. Write-behind optimizes write throughput and accepts a data-loss window on cache failure.2

The non-linearity is what catches teams off guard: a hit-rate drop from 99% to 98% doubles database load.3 That single percentage point is the difference between a healthy system and a cascading failure.

Diagram
Cache-aside lets the application own miss logic; write-through waits for DB confirmation; write-behind returns immediately and risks losing unflushed writes.
sequenceDiagram
    participant App
    participant Cache
    participant DB
    Note over App,DB: Cache-aside (read path)
    App->>Cache: GET key
    alt hit
        Cache-->>App: value
    else miss
        Cache-->>App: nil
        App->>DB: SELECT
        DB-->>App: row
        App->>Cache: SETEX key TTL value
    end
    Note over App,DB: Write-through (write path)
    App->>Cache: PUT key=v
    Cache->>DB: INSERT/UPDATE
    DB-->>Cache: ack
    Cache-->>App: ok
    Note over App,DB: Write-behind (write path)
    App->>Cache: PUT key=v
    Cache-->>App: ok (NOT yet in DB)
    Cache->>DB: async batch flush

Side-by-Side Comparison

DimensionCache-AsideWrite-ThroughWrite-Behind
Read latency (hit)Sub-msSub-msSub-ms
Read latency (miss)DB latency + cache writeDB latency (via cache loader)Sub-ms (always in cache)
Write latencyDB write + cache deleteDB write + cache write (serial)Cache write only (~1 us)
ConsistencyEventual (bounded by TTL)Read-your-writesEventual (bounded by flush interval)
DurabilityFull (DB is authoritative)FullAt risk: flush interval = data-loss window4
Cache pollutionLow (only requested data cached)High (all writes enter cache)High
Operational complexityApp owns invalidationCache library owns coherenceFlush monitoring, crash recovery
Failure modeThundering herd on cold startWrite amplification on hot keysSilent data loss on crash2

The table misleads on one dimension: write-through’s “full durability” assumes the DB write succeeds before the cache is updated. If you update the cache first and the DB write fails, you have a stale cache entry with no TTL to save you. Order matters: DB first, cache second.3

Write-behind’s “sub-ms read latency” is only true if the reader goes through the cache. Any read that bypasses to the database sees stale data until the next flush.2

When to Pick Cache-Aside

  • Read:write ratio exceeds 10:1. Facebook Memcache serves billions of reads per second with ~99% hit rate against MySQL backends that handle ~100K queries/sec per server.3 The 10x gap between cache and DB throughput is the economic argument.
  • Cache is a performance layer, not a correctness layer. If Redis goes down, the system degrades to database-only operation. Painful, but not data-losing.
  • Multiple services read the same keys. Each service manages its own get-or-populate logic. No central cache library required.
  • You can tolerate bounded staleness. TTL caps the blast radius of invalidation bugs to seconds or minutes, not forever.1
  • Write patterns are diverse. Many code paths update the same entity. Using delete (not set) on write avoids the stale-set race under concurrent updates.3

When to Pick Write-Through/Write-Behind

Write-through when:

  • Read-your-writes is a hard product requirement. Account balances, RBAC permissions, feature-flag state. A user who changes their password must not see the old one on the next page load.
  • The write rate is modest. DynamoDB DAX uses write-through for PutItem and UpdateItem; the extra latency is acceptable because DynamoDB writes are already single-digit ms.2
  • You want zero drift between cache and DB. Facebook TAO uses write-through from leader caches to MySQL, eliminating the invalidation-race bugs that plagued raw Memcache.5

Write-behind when:

  • Write throughput is the bottleneck and the data is reconstructable. View counters, analytics events, personalization signals. Losing one second of counter increments is not a correctness bug.
  • You need 10-100x write throughput improvement. Redis AOF with appendfsync everysec is write-behind at the durability layer: up to one second of writes can be lost on crash.4
  • Batching and coalescing reduce backend load. Multiple updates to the same key collapse into one DB write, cutting write amplification.2

The Hybrid Path

Most production systems default to cache-aside for reads and layer write-through onto the small set of fields where read-your-writes is a product requirement. Write-behind appears narrowly for high-throughput, low-value writes. Mixing strategies per field is the norm, not the exception.16

Diagram
Classify each field by its consistency and durability needs; most systems run all three strategies simultaneously on different data.
flowchart TD
    A[Incoming write] --> B{Field classification}
    B -->|Critical: balance, permissions| C[Write-through]
    B -->|Standard: profile, preferences| D[Cache-aside with delete]
    B -->|High-volume: counters, telemetry| E[Write-behind]
    C --> F[DB + cache updated synchronously]
    D --> G[DB updated, cache key deleted]
    E --> H[Cache updated, async flush to DB]

Facebook’s architecture demonstrates this: Memcache (cache-aside) handles the general read workload, TAO (write-through) handles the social graph where invalidation races are unacceptable, and internal counters use write-behind for throughput.53

Real-World Examples

Facebook Memcache (2013). Billions of requests/sec, trillions of items, ~99% hit rate.7 Cache-aside with delete on write (not set) because delete is commutative under concurrent updates. Leases serialize thundering-herd refills: on miss, Memcached hands a one-time token to the first requester; others retry. McSqueal tails the MySQL binlog to broadcast cross-region invalidations.3

Facebook TAO (2013). Over 1 billion reads/sec, millions of writes/sec across a large fleet of geographically distributed server clusters.5 Write-through from leader caches to MySQL. Two-tier topology (followers serve reads, leaders own writes) reduces MySQL fan-in. The team switched from cache-aside specifically because the stale-set races in Memcache were too costly for graph data.5

Netflix EVCache (2024). As of 2024, 400 million ops/sec, 14.3 PB across 22,000 instances in four AWS regions.8 Cache-aside with client-initiated cross-region replication via Kafka (metadata-only payloads, not values). SSD-backed tier (extstore) trades higher latency for significantly lower cost per GB versus RAM-only.8

Common Mistakes

Decision Checklist

  • What is the read:write ratio? If >10:1, cache-aside is almost always correct.
  • Does the user see stale data after their own write? If yes, write-through for that field.
  • If the cache crashes with N unflushed writes, what is the business impact?
  • Is your invalidation strategy correct across all cache replicas and all regions?
  • Do you have a TTL on every cached key, even as a backstop?
  • Are you monitoring cache hit rate as a first-class SLI?
  • Is the data reconstructable from an upstream source? If not, write-behind is off the table.

Key Takeaways

  • Cache-aside is the default. It works for >90% of read-heavy workloads and degrades gracefully on cache failure.
  • Write-through buys read-your-writes at the cost of write latency. Use it narrowly for fields where staleness is a correctness bug.
  • Write-behind is the strategy that will silently eat your data. Restrict it to reconstructable, high-volume writes.
  • Always use delete (not set) on the write path to avoid stale-set races under concurrency.3
  • TTL is both a freshness knob and a bug blast-radius cap. Set one on every key.

Further Reading

Flashcards

Why use delete instead of set on the cache write path?

Delete is commutative under concurrent writes. Two overlapping writes with set can leave permanently stale data in cache (the slower write’s value arrives last). Delete ensures the next read populates from the authoritative database.3

What is the data-loss window for write-behind?

The flush interval. For Redis AOF with appendfsync everysec, up to one second of acknowledged writes can be lost on crash. For custom batch flushes, the window equals the batch period.4

Why does a 1% hit-rate drop from 99% to 98% double DB load?

At 99% hit rate, 1% of requests reach the DB. At 98%, 2% reach the DB. The miss rate doubled (1% to 2%), so DB load doubles. The relationship between hit rate and DB load is non-linear near high hit rates.3

When should you pick write-through over cache-aside?

When read-your-writes is a hard product requirement (account balances, permissions, feature flags) and the write rate is modest enough to absorb the extra latency of writing to both cache and DB synchronously.2

What is the thundering-herd problem and how did Facebook solve it?

When a popular key expires, N concurrent requests all miss and query the DB simultaneously. Facebook’s Memcache uses leases: on miss, the cache hands a one-time token to the first requester. Others retry with backoff. Only one DB read happens per key per miss event.3

Why do most production systems use a hybrid of cache strategies?

Different fields have different consistency and durability requirements. Account balances need write-through (read-your-writes). Profile data tolerates cache-aside (bounded staleness). View counters use write-behind (throughput over durability). Classifying per field is the norm.16

What role does TTL play beyond freshness?

TTL is a blast-radius cap on invalidation bugs. Even if your invalidation logic has a race condition or a missed code path, the stale value expires after TTL seconds. Without TTL, a bug means stale data lives forever.1

Diagram
Start with cache-aside as the default; escalate to write-through only for fields where staleness is a correctness bug; write-behind is only safe for reconstructable data.
graph TD
    A[Need a cache strategy?] -->|Read:write > 10:1| B[Cache-aside]
    A -->|Read-your-writes required| C[Write-through]
    A -->|Write throughput bottleneck| D{Data reconstructable?}
    D -->|Yes| E[Write-behind]
    D -->|No| C
    B --> F{Staleness acceptable?}
    F -->|Yes, bounded by TTL| G[Done: cache-aside + TTL + delete on write]
    F -->|No, for specific fields| H[Hybrid: cache-aside + write-through for critical fields]

References

Footnotes

  1. AWS Caching Best Practices whitepaper. https://aws.amazon.com/caching/best-practices/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7

  2. Joseph Idziorek, “Amazon DynamoDB Accelerator (DAX): A Read-Through/Write-Through Cache for DynamoDB”, AWS Database Blog, 2017. https://aws.amazon.com/blogs/database/amazon-dynamodb-accelerator-dax-a-read-throughwrite-through-cache-for-dynamodb/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  3. Robert Morris, MIT 6.824 lecture notes on Nishtala et al., “Scaling Memcache at Facebook”. https://pdos.csail.mit.edu/6.824/notes/l-memcached.txt ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12

  4. Redis Persistence (AOF appendfsync) docs. https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/ ↩ ↩2 ↩3 ↩4

  5. Mark Marchukov, “TAO: The power of the graph”, Engineering at Meta, 25 Jun 2013. https://engineering.fb.com/core-data/tao-the-power-of-the-graph/ ↩ ↩2 ↩3 ↩4

  6. AWS Database Caching Strategies Using Redis: Caching Patterns. https://docs.aws.amazon.com/whitepapers/latest/database-caching-strategies-using-redis/caching-patterns.html ↩ ↩2

  7. Nishtala et al., “Scaling Memcache at Facebook”, NSDI 2013. https://www.usenix.org/conference/nsdi13/technical-sessions/presentation/nishtala ↩

  8. Rangarajan & Karumanchi, “Building a Global Caching System at Netflix: a Deep Dive to Global Replication”, InfoQ, Oct 2024. https://www.infoq.com/articles/netflix-global-cache/ ↩ ↩2

Finished reading?

Mark it complete to track your progress through the course. Progress is saved in this browser.

This lesson is adapted from “Cache Strategies: Cache-Aside vs Write-Through vs Write-Behind” in The Engineering Handbook by Handbook Academy and contributors, used under CC BY-SA 4.0. Changes: restyled and reorganized for this site. View original source.