Intermediate8 min readlive prototype

Write-Around

Writes skip the cache entirely. Keeps the cache clean for hot reads, costs you on re-reads.

Overview

What this concept solves

Write-around is the contrarian policy. Every write bypasses the cache and goes straight to the backing store. The cache is reserved for reads. The bet: most of what gets written won't get read back any time soon, so caching writes is wasted space.

The cache stays clean and small, holding only data that's actually being read. The cost: if a key gets written and then read soon after, that first read is a guaranteed miss — the cache never saw the write.

Mechanics

How it works

Writes skip the cache entirely

  1. Write any key — go straight to the backing store. The cache is not touched.
  2. If that key was already cached — invalidate the existing line. Otherwise the cache would return a stale value on the next read.
  3. Read miss — load from the store, populate the cache, return.
  4. Read hit — return from cache. Reads behave like a normal read-only cache.

Invalidation is the subtle part

If a write doesn't invalidate the matching cache line, the cache silently keeps serving the OLD value forever. Most production write-around implementations get this wrong at least once. The simulator flashes the invalidated line red on purpose — that step is where the policy lives or dies.

Interactive prototype

Run it. Break it. Tune it.

Sandboxed simulation embedded right in the page. No setup, no install.

About this simulation

A 4-line cache reserved for reads only. Every write curves around the cache straight to memory along the violet arc — the cache stays cold for that address until something actually reads it. If the address was in the cache, the existing line is invalidated (red flash) so it can't return stale data. Hit Demo to watch reads populate the cache, a write invalidate the matching line, and cold writes leave the cache untouched.

Hands-on

Try these on your own

Open the prototype above, run each experiment, predict the answer, then verify.

try 01

Read first, write second — see invalidation

Pick 0x00, hit Read — a cache miss, the value loads into line 0. Now write a new value to 0x00. Watch the cache line flash red (invalidated) and disappear. Memory got the new value; the cache went cold for that key.

try 02

Write a key that was never read — cache untouched

Pick 0x10 (or any other address), hit Write. The dot curves straight from CPU around the cache to memory. The cache lines on the left are unchanged — write-around protected them.

try 03

Compare to write-through's behavior

In write-through, that same write would have allocated 0x10 into the cache. In write-around, the cache stays focused on what readers actually want. Open the write-through simulator in a second tab and run identical sequences to see the cache shape diverge.

In practice

When to use it — and what you give up

When to reach for it

  • Write-once, read-rarely workloads — log ingestion, telemetry, archival uploads, append-only audit trails. Most writes never get read at all.
  • Large blobs that would flush hot keys — uploading a 10 MB file shouldn't push the small hot session keys out of the cache.
  • You already have a read-through cache and want to protect it from scan-like write patterns — write-around keeps writes from polluting an LRU.
  • The write path is rare — read:write ratio is 100:1 or higher. Why design the cache around the cold path?

Real-world example

CDN edge caches are usually write-around against origin uploads: when you PUT to S3 via CloudFront, the edge invalidates any cached copy, the object lives on origin, and the next GET populates the cache. Redis-in-front-of-Postgres patterns often use write-around for bulk inserts: writes go straight to Postgres, the application invalidates affected keys in Redis, reads pull through. CPU write-no-allocate is the same idea at the silicon level — writes that miss the cache don't allocate a line.

Pros

  • Cache never pollutes — only data that's been read lives in the cache, so the cache always reflects the read workload.
  • Big writes don't evict hot reads — uploading 1 GB doesn't kick your session keys out.
  • Durability is safe — the store is the only writer, so the cache can't hold dirty data the store doesn't have.
  • Simple to bolt on top of a read-through cache — writes go straight to the source; the cache only sees reads.

Cons

  • First read after a write is always a miss — if your workload has read-after-write patterns, write-around will hurt.
  • Invalidation is required — without it, the cache serves stale values forever after a write.
  • No write-throughput help — every write hits the store at full latency. Write-around is a read optimization, not a write optimization.
  • Doesn't protect the store — write-back's coalescing benefit is gone; the store sees every write directly.

Reference

Code & further reading

A minimal reference implementation and pointers worth bookmarking.

write-around.ts
// Write-around: writes skip the cache, only reads populate it.
// Invalidation is mandatory — otherwise reads return stale values.
class WriteAroundCache<K, V> {
  private cache = new Map<K, V>();
  constructor(
    private capacity: number,
    private store: { get(k: K): V | undefined; put(k: K, v: V): void },
  ) {}

  get(key: K): V | undefined {
    if (this.cache.has(key)) return this.cache.get(key);
    const v = this.store.get(key);
    if (v !== undefined) this.admit(key, v);
    return v;
  }

  set(key: K, value: V): void {
    // Always write directly to the store...
    this.store.put(key, value);
    // ...and invalidate any cached copy. Skipping this step is the
    // most common bug in write-around implementations.
    this.cache.delete(key);
  }

  private admit(key: K, value: V) {
    if (this.cache.size >= this.capacity) {
      const oldest = this.cache.keys().next().value!;
      this.cache.delete(oldest);
    }
    this.cache.set(key, value);
  }
}

References & further reading

3 sources

Knowledge check

Did the prototype land?

Quick questions, answers revealed on submit. No scoring saved.

question 01 / 03

Under write-around, what happens to the cache on a write to a key that's already cached?

question 02 / 03

Which workload is the *worst* fit for write-around?

question 03 / 03

Which problem does write-around solve that write-through does not?

0/3 answered

Was this concept helpful?

Tell us what worked, or what to improve. We read every note.