Stop 11 · CachingTopics · 7/8

Write-Through vs Write-Behind

Part of the Backend Developer Roadmap

In short

Reading through a cache is one problem. Writing is another: do you update the database first, the cache first, or both together? Each answer trades safety against speed.

Two strategies for keeping cache and database in sync on writes — write-through updates both immediately (safer, slower); write-behind updates the cache immediately and the database asynchronously (faster, riskier).

The blob character writes in a big ledger while a tray of paper slips waits beside it.

Think of it like this

The ledger and the slip tray

One shopkeeper writes every sale straight into the big ledger before handing back change. Another jots sales on slips and copies them into the ledger at night. The first is slower but never loses a sale. The second is quicker, until the slip tray falls over.

Watch it happen

Saving data through a cache

Write-through

  • Write cache and database together
  • The request waits for the database
  • Data is safe once acknowledged

Write-behind

  • Write cache now, database later
  • Very fast acknowledgement
  • A crash before flushing loses writes

Use write-through, or plain cache-aside, for money, orders and anything you can't lose. Write-behind suits counters, views and analytics.

The big ideas

What you need to know

Write-through stays consistent

Every write updates the database and the cache in the same request, so reads right after are correct.

Write-behind is fast

Writes land in the cache first and reach the database later in batches. Great for heavy write traffic.

Write-behind can lose data

If the cache dies before flushing, those writes are gone. Use a durable queue if that matters.

Batching saves the database

Turning 10,000 'views + 1' writes into one UPDATE every few seconds is write-behind at its best.

See it in code

Walk through the code

ts
1// Write-behind: count views in Redis, flush to Postgres every 10s2export async function recordView(postId: number) {3  await redis.hIncrBy("views:pending", String(postId), 1);4}5 6setInterval(async () => {7  if (!(await redis.exists("views:pending"))) return;8  await redis.rename("views:pending", "views:flushing");9  const pending = await redis.hGetAll("views:flushing");10  for (const [postId, count] of Object.entries(pending)) {11    await pool.query("UPDATE posts SET views = views + $1 WHERE id = $2", [Number(count), Number(postId)]);12  }13  await redis.del("views:flushing");14}, 10_000);

1/3Each view is a cheap increment in a Redis hash. The request returns instantly.

If Redis restarts before a flush, up to 10 seconds of views are lost. That's fine for view counts, never for payments.

Save yourself the pain

Common mistakes

Oops

Using write-behind for orders or payments to make checkout feel faster.

Do this instead

A crash could lose confirmed orders. Write money data to the database first and cache it afterwards.

Oops

Assuming write-through means the cache can never be wrong.

Do this instead

If the database write succeeds but the cache write fails, they differ. Keep TTLs as a safety net.

Your mission

Batch your view counts

~30 min

Quick check

Which data is the best fit for write-behind?

Go deeper

  1. 1Diagram the request flow for both write-through and write-behind on a write operation.
  2. 2Identify a scenario where write-behind's risk of data loss would be unacceptable.
  3. 3Understand these patterns matter most for extremely write-heavy, latency-sensitive systems.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge