Lesson 0005 · Persistence & durability

Persistence: RDB vs AOF

How an in-memory, single-threaded server saves to disk without freezing every client.

~11 minRetrieval quiz at the endCheat sheet: here

Redis lives in RAM — so a crash or restart would vaporize everything unless it wrote to disk. But recall the keystone from Lesson 0001: one thread runs every command. If that thread stopped to write gigabytes to disk, every client would stall for the whole write. This lesson is how Redis escapes that trap — with two persistence modes (RDB snapshots and the AOF log) and one beautiful OS trick (fork() + copy-on-write) that lets the single thread keep serving while a child process does the disk I/O.

Part 1 — Two ways to persist

RDB — point-in-time snapshots

RDB writes a compact binary snapshot of the whole dataset at intervals — "a very compact single-file point-in-time representation of your Redis data." You configure triggers like save 60 1000 (snapshot if ≥1000 keys changed in 60s), or fire one manually. Redis Docs — Persistence

AOF — the append-only log

AOF takes the opposite approach: "logs every write operation received by the server. These operations can then be replayed again at server startup, reconstructing the original dataset." It's a write-ahead-style journal of commands, not a snapshot of state. Redis Docs — Persistence

How often the log is flushed to disk (fsync) is the durability dial — appendfsync:

appendfsyncfsync cadenceWorst-case loss
alwaysevery write≈ nothing — "very very slow, very safe"
everysec (default)once per second~1 second of writes
noOS decides (~30s on Linux)up to ~30 seconds

"The suggested (and default) policy is to fsync every second. It is both fast and relatively safe." (antirez notes the worst case is bounded by ~2 seconds, not exactly 1.) Docs · antirez — persistence demystified

Part 2 — The trick: fork() + copy-on-write

Here's how a single thread persists without blocking. To snapshot (or rewrite the AOF), Redis calls fork(): the OS creates a child process that does all the disk I/O, while the parent keeps executing commands. "The parent process will never perform disk I/O." Redis Docs

Why fork() is cheap (copy-on-write)

The child doesn't copy the dataset. After fork(), parent and child share the same physical memory pages, read-only. Only when the parent modifies a page does the OS copy that page"Redis [benefits] from copy-on-write semantics." So the extra memory a snapshot needs is proportional to how much data changes during the save, not the size of the whole dataset. The child writes a frozen, consistent point-in-time view.

The cost — a latency spike (ties back to Lesson 0001)

fork() itself isn't free: "fork() can be time consuming if the dataset is big, and may result in Redis stopping serving clients for some milliseconds or even for one second if the dataset is very big." On the single thread, that fork pause is head-of-line blocking. Big instances + heavy writes (more pages to copy) = bigger spikes. Redis Docs

The AOF has the same growth-and-fork story: the log keeps growing, so AOF rewrite (BGREWRITEAOF) forks a child that writes "the shortest sequence of commands needed to rebuild the current dataset" — compacting the log using the same copy-on-write trick. Redis Docs

Part 3 — Durability trade-offs, and which to use

RDB (snapshot)AOF (log)
DurabilityLose minutes since last snapshotLose ≤ ~1s (with everysec)
FileCompact single binary — great for backups/DRLarger; needs periodic rewrite to shrink
Restart speedFaster with big datasetsSlower — replays the log
Steady-state costFork only when snapshottingAppends continuously (+ rewrites)
The recommendation

Use both. The docs: "use both persistence methods is if you want a degree of data safety comparable to what PostgreSQL can provide you." RDB gives you cheap backups and fast restarts; AOF gives you a tight data-loss window. AOF alone is discouraged because an occasional RDB is invaluable for backups and faster restarts. Redis Docs

Check yourself

Answer from memory — effortful recall builds retention. Two questions revisit earlier lessons on purpose (spacing).

RDB persists the dataset by having Redis:

BGSAVE forks a child process that does all the disk I/O while the parent keeps serving commands. SAVE (main-thread, blocking) exists but is a production anti-pattern.

Copy-on-write means the snapshot's extra memory is proportional to:

Parent and child share pages read-only; only pages the parent modifies during the save get copied. So overhead scales with the write churn during the snapshot, not the whole dataset.

With appendfsync everysec, a crash loses at most about:

everysec fsyncs the AOF once per second — the default, and the sweet spot. always loses ~nothing but is much slower; no can lose ~30s.

For data safety comparable to PostgreSQL, the docs recommend:

Use both: RDB for compact backups and fast restarts, AOF for a tight (~1s) data-loss window. AOF-only is discouraged because occasional RDB snapshots are invaluable.

Interleave — a fork() for a big snapshot can cause what, per Lesson 0001?

The fork pause happens on the one command thread, so every client waits behind it — head-of-line blocking. Bigger dataset + more write churn = bigger spike.

Interleave — which command atomically elects one request to rebuild a cache key?

From Lesson 0004: SET ... NX succeeds for only the first caller (single-threaded atomicity) — the single-flight lock that stops a stampede.

Hands-on: snapshot, then switch on the log

You need a local Redis and redis-cli.

1 · Trigger a snapshot and read its status

redis-cli CONFIG GET save                 # the automatic snapshot rules
redis-cli SET a 1
redis-cli BGSAVE                          # fork a child, snapshot in background
redis-cli INFO persistence | grep -E 'rdb_last_bgsave_status|rdb_changes_since_last_save|rdb_last_save_time'

2 · Enable AOF and watch a rewrite

redis-cli CONFIG SET appendonly yes
redis-cli CONFIG GET appendfsync          # -> everysec (the default)
redis-cli MSET x 1 y 2 z 3
redis-cli BGREWRITEAOF                     # compact the log via a forked child
redis-cli INFO persistence | grep -E 'aof_enabled|aof_last_bgrewrite_status|aof_rewrite_in_progress'
Predict first

After BGSAVE, what does rdb_changes_since_last_save reset to, and why? And if you killed Redis one second after a write with only everysec AOF, how much would you lose? Commit, then check.

Clean up: redis-cli CONFIG SET appendonly no, then redis-cli FLUSHALL. Bring any surprising INFO persistence field to your teacher.

Primary source — read this next

Redis Docs — Persistence is the authoritative page: RDB vs AOF, the fork/COW mechanism, appendfsync, and the "use both" guidance. For the author's own deep dive, read antirez — Redis persistence demystified.