CachingCache Invalidation StrategiesMedium⏱️ ~3 min

Write Path Patterns: Write Through, Write Behind, and Cache Aside with Delete on Write

Your choice of write path pattern determines when and how caches update during data mutations, fundamentally affecting write latency, consistency guarantees, and failure modes. Write through updates both cache and origin synchronously: writes block until both succeed, providing strong consistency (reads immediately see writes) at the cost of higher write latency (sum of cache and origin latency). Write behind updates cache immediately and queues origin writes asynchronously, offering low write latency but risking data loss on crashes and creating windows of inconsistency where cache and origin diverge. Cache aside with delete on write (the most common pattern at scale) commits to origin first, then invalidates cache entries, leaving reads to repopulate cache lazily; this separates write and cache concerns but introduces race conditions where concurrent reads can repopulate stale data during invalidation. Cache aside with delete on write is the dominant pattern in production systems like Meta's Memcache and Pinterest's multi tier caches because it balances simplicity, fault tolerance, and performance. The sequence is critical: first commit your write to the source of truth (database), ensuring durability, then delete (or invalidate) affected cache keys. This commit before invalidate ordering prevents stale data from being cached indefinitely. However, a race condition exists: if a read happens between commit and invalidation (or during invalidation), it might fetch the old value from origin and repopulate the cache with stale data. Meta mitigates this with leases: when a cache miss occurs, the client receives a short lived lease token; when populating the cache, it includes the lease, and the cache rejects the set if it has seen an invalidation for that key since issuing the lease. This prevents the stale repopulation window from persisting beyond a few milliseconds. Additionally, including version numbers in cached values allows readers to detect and discard stale entries even if they make it into cache. Write through makes sense when read your writes consistency is critical and write latency can absorb extra hops: counters visible to users (likes, votes) where immediate feedback matters, inventory systems where selling out of stock is costly, and session data where stale reads cause user visible errors. Write behind is rare at scale due to data loss risk, but appears in specialized scenarios like write heavy logging systems where loss of a few log entries is acceptable for massive throughput gains, or with careful durability mechanisms like write ahead logs and periodic checkpoints. The numbers: cache aside typically adds 0.5 to 2 milliseconds of write latency for invalidation messages compared to baseline, while write through doubles write latency (database 5 milliseconds plus cache 1 millisecond equals 6 milliseconds) unless parallelized. Most systems default to cache aside with TTL as safety net, reserving write through for specific high value consistency requirements.
💡 Key Takeaways
Write through synchronously updates both cache and origin, guaranteeing read your writes consistency but doubling write latency (database 5 milliseconds plus cache 1 millisecond equals 6 milliseconds) unless parallelized, suitable for user facing counters and inventory
Write behind asynchronously queues origin writes after updating cache, achieving low write latency but risking data loss on crashes and creating consistency windows where cache and origin diverge, rarely used at scale without strict durability mechanisms
Cache aside with delete on write commits to origin first then invalidates cache, separating write and cache layers for fault tolerance, but introduces race where reads between commit and invalidation can repopulate stale data for milliseconds to seconds
Commit before invalidate ordering is critical: invalidating before commit allows stale data to be cached indefinitely when the next read fetches old origin data, while commit first ensures stale cache entries eventually get correct data
Meta uses lease based reads to close race windows: cache issues short lived tokens on misses, and rejects cache sets if an invalidation occurred since the lease was issued, preventing stale repopulation from persisting beyond milliseconds
Default choice is cache aside with TTL safety net for 95% of use cases, reserving write through for specific correctness requirements where write latency budget allows absorbing synchronous cache updates
📌 Examples
Meta's Memcache uses cache aside with delete on write for social graph objects: write commits to MySQL, then deletes cache keys via Memcache delete protocol, with lease tokens preventing stale repopulation during the invalidation window, handling over 1 billion operations per second
An e commerce cart uses write through for inventory decrements: when user adds item to cart, synchronously update Redis counter and database row, blocking write for 6 to 10 milliseconds but ensuring immediate consistency so two concurrent buyers cannot both succeed on last item
A high throughput analytics pipeline uses write behind for event logging: writes hit in memory cache in under 0.5 milliseconds returning success, then flush to persistent storage every 5 seconds in batches, accepting potential loss of 5 seconds of data on crash for 10x throughput
← Back to Cache Invalidation Strategies Overview
Write Path Patterns: Write Through, Write Behind, and Cache Aside with Delete on Write | Cache Invalidation Strategies - System Overflow