Command Palette

Search for a command to run...

Hectal
PHASE 6Intermediate ~10 min· topic 2 of 7

Topic 6.2

Read-Through, Write-Through, and Write-Behind

In one line

Read-through moves loading logic into the cache layer; write-through writes the cache and database together for fresher reads; write-behind writes the cache first and flushes to the database asynchronously for speed, at the risk of losing writes. Each moves responsibility and risk to a different place.

0/7 · 0%

Think of it like this

Three ways to run a hotel front desk. Read-through: guests only talk to the receptionist, who fetches files from the back office when needed. Write-through: every update is written in the desk ledger and the back-office ledger before the guest leaves. Write-behind: the receptionist jots it down and files it in the back office later; faster, until the notepad gets lost.

Key ideas

  1. 01

    Read-through: the application asks a cache component (a library or a caching proxy) for a key; on a miss, the cache itself calls a loader to fetch from the database. It centralises loading logic and makes request coalescing easy (the loader runs once per key). Spring's @Cacheable, Caffeine's LoadingCache, and Redisson's RMapCache with a loader are examples. Redis itself doesn't call your database; the pattern lives in your code or library.

  2. 02

    Write-through: every write goes to the database and the cache synchronously (the cache layer or the application updates both). Reads right after a write hit a fresh cache. Write latency is higher (two writes), the cache fills with data that may never be read, and the two writes still aren't atomic, so one can fail after the other succeeds.

  3. 03

    Write-behind (write-back): writes go to Redis only and return immediately; a background process flushes them to the database in batches. Great for very high write rates (counters, likes, game state) and absorbing bursts. Risks: data loss if Redis loses unflushed writes, ordering problems, and a database that lags Redis.

  4. 04

    Making write-behind safer: record changes in a Redis Stream (XADD) rather than just overwriting values, flush with consumer groups and acks, make flushes idempotent (upserts with version checks), and enable AOF. If losing a few seconds of writes is unacceptable, don't use write-behind for that data.

  5. 05

    Refresh-ahead is a related pattern: reload popular entries shortly before they expire so users never see a miss (Topic 6.5).

Code & diagrams

patterns.mermaiddiagram
Rendering diagram…
write-behind-flusher.pypython

Writes are recorded in a stream so the flusher can batch, retry and acknowledge.

import redis
r = redis.Redis(decode_responses=True)

def like(post_id: int, user_id: int):
    pipe = r.pipeline()                              # MULTI/EXEC
    pipe.hincrby("likes:count", post_id, 1)
    pipe.xadd("likes:changes", {"post": post_id, "user": user_id}, maxlen=1_000_000, approximate=True)
    pipe.execute()

def flush_forever(db):
    try:
        r.xgroup_create("likes:changes", "flusher", id="0", mkstream=True)
    except redis.ResponseError:
        pass
    while True:
        batch = r.xreadgroup("flusher", "f1", {"likes:changes": ">"}, count=500, block=2000)
        for _, entries in batch:
            rows = [(int(f["post"]), int(f["user"])) for _, f in entries]
            db.executemany(
                "INSERT INTO likes(post_id, user_id) VALUES (%s, %s) ON CONFLICT DO NOTHING", rows)
            db.commit()                              # idempotent upsert
            r.xack("likes:changes", "flusher", *[i for i, _ in entries])

Interview problem

The problem

Pick a write strategy for three features

Choose between cache-aside, write-through and write-behind for: (1) user profile edits, (2) post like counts at 100K likes/sec at peak, (3) bank account balances. Explain consistency, write latency, durability, ordering, data loss and replay for each.

The interviewer follows up

01

In write-through, what if the database write fails after the cache write succeeded?

When it breaks

Write-behind with values only (no change log) and no persistence

What you see

A Redis crash loses every write since the last flush; with overwrites there's no record of what was lost.

Fix & prevent

Log changes in a Stream with consumer groups, enable AOF, keep flush intervals short, and reconcile against the database.

Explain it without notes

01

Who is responsible for loading missing data in read-through vs cache-aside?

Practice

01

Sketch write-behind for game player state (position, inventory) saved every 30 seconds to the database.

Trade-offs

  • ↔

    Write-through: fresher cache, slower writes, cache full of unread data.

  • ↔

    Write-behind: fastest writes and burst absorption, at the cost of durability and eventual consistency with the database.

Done when you can

  • I can explain read-through, write-through, write-behind and refresh-ahead.

  • I can choose a write strategy based on the cost of losing a write.

  • I can make write-behind safer with a stream, acks and idempotent flushes.