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).

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
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
Quick check
Which data is the best fit for write-behind?
Go deeper
- 1Diagram the request flow for both write-through and write-behind on a write operation.
- 2Identify a scenario where write-behind's risk of data loss would be unacceptable.
- 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.