Beginner8 min readlive prototype

Write-Through

Every write goes to cache and the backing store in lockstep. Simple, safe, and slow.

Overview

What this concept solves

Write-through is the simplest write policy. Every write goes to the cache AND the backing store, at the same time. The cache and the store are always in lockstep — the cache is never holding data the store doesn't have.

It's the policy you reach for when the cache is an optimization, not a buffer. Reads can still hit the fast path. But writes are bound by the slow path, because they don't return until the store has confirmed the update.

Mechanics

How it works

Three steps, every write

  1. Write to the cache line — update the value in the fast layer.
  2. Write to the backing store — propagate the same value down.
  3. Acknowledge the write — return to the caller only after the store has accepted it.

Because both layers carry the same value at all times, there's no notion of a 'dirty' line — every line is clean. Eviction is trivial: drop the entry, do nothing else, the store already has the canonical copy.

Write-allocate or no-write-allocate?

On a write miss, you can either pull the line into the cache (write-allocate) or skip it (no-write-allocate). Write-through is most often paired with no-write-allocate — there's no point bringing a line in just to mirror what the store already has. Pair it with write-allocate only if you expect that key to be read back immediately.

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 direct-mapped cache in front of 8 memory cells. Hit Demo to watch the canonical sequence, or pick an address, type a value and Write — both the cache line and the memory cell light up on every write. The stats prove the policy: Writes and Memory writes stay equal, forever. Read to see a cache hit save the trip; the cache still mirrors memory exactly.

Hands-on

Try these on your own

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

try 01

Watch the two columns move together

Open the simulator. Pick 0x00, set value to 99, hit Write. Watch both dots fire at once — one to the cache, one to memory. The Writes and Memory writes stats both tick up by 1. They will stay equal no matter what you do.

try 02

Read after write — confirm there's no drift

After the write, hit Read on the same address. The cache answers (hit), and the value matches what memory shows on the right. Write-through guarantees this: cache and store carry the same value at all times.

try 03

Write the same key 5 times

Pick one address, write 5 different values back-to-back. The Memory writes counter climbs to 5 — write-through paid the full memory-write cost on every single one, even though only the last value will ever be read.

In practice

When to use it — and what you give up

When to reach for it

  • Durability is non-negotiable — payments, ledgers, audit logs, anywhere a lost write is a real incident.
  • Multi-reader workloads — if other processes read directly from the store, you can't afford the cache to be ahead of it.
  • The store is fast enough — local SSD, an in-process DB, or a write-optimized engine. The latency hit hurts less when the store isn't the bottleneck.
  • Read-heavy traffic — writes are infrequent enough that paying full latency on each one doesn't dominate.

Real-world example

Most CPU L2/L3 caches in older designs were write-through to simplify cache-coherence between cores. The Postgres write-ahead log is logically write-through against the WAL file: every transaction commit waits for fsync before returning. Many CDN configurations are write-through against the origin so that a stale edge never lies to a client.

Pros

  • Crash-safe by construction — the store is always authoritative. A power loss never costs you a write.
  • No dirty bookkeeping — every cache line is clean, eviction is free.
  • Trivial consistency — readers going straight to the store get the same value the cache would return.
  • Easy to reason about — no flush queues, no write-back coalescing windows, no async durability ladder.

Cons

  • Slow writes — every write blocks on the backing store. If the store is remote or slow, write latency suffers proportionally.
  • Wastes write bandwidth — writing the same key 100 times costs 100 store writes, even though only the last value matters.
  • Pointless under write-around-able workloads — if the data won't be re-read, you paid the store-write cost AND the cache-write cost for no benefit.

Reference

Code & further reading

A minimal reference implementation and pointers worth bookmarking.

write-through.ts
// Write-through cache: every write updates both layers.
// No dirty flag — lines are always in sync with the store.
class WriteThroughCache<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 {
    // 1. update cache (only if key is already cached — no-write-allocate)
    if (this.cache.has(key)) this.cache.set(key, value);
    // 2. always update the backing store, synchronously
    this.store.put(key, value);
  }

  private admit(key: K, value: V) {
    if (this.cache.size >= this.capacity) {
      // eviction is free — every line is clean
      const oldest = this.cache.keys().next().value!;
      this.cache.delete(oldest);
    }
    this.cache.set(key, value);
  }
}

References & further reading

4 sources

Knowledge check

Did the prototype land?

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

question 01 / 03

Under write-through, when does a write to a cached key get acknowledged to the caller?

question 02 / 03

Why does write-through have no concept of a 'dirty' cache line?

question 03 / 03

Your workload writes the same hot key 100 times per second and the backing store is a remote database. What's the main cost of using write-through here?

0/3 answered

Was this concept helpful?

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