Lesson 0006 · Replication & scaling

Replication & async trade-offs

Copying a primary to survive a dead machine — and the writes that async replication can lose.

~11 minRetrieval quiz at the endCheat sheet: here

Lesson 0005 made your data survive a restart. But a restart isn't the machine dying — a failed disk or a vanished cloud instance takes the whole process with it. Replication is the answer: keep a live copy on another machine. It's also where your idea from last lesson — "offload the snapshot to a replica" — comes true. The catch, and the whole point of this lesson, is that Redis replication is asynchronous by default, which buys speed at the price of a narrow window where an acknowledged write can vanish.

Part 1 — The leader-follower model

Redis uses "leader follower (master-replica) replication… It allows replica Redis instances to be exact copies of master instances." One primary, many replicas; a replica can even have its own sub-replicas (cascading). Redis Docs — Replication

Part 2 — How a replica syncs

Every primary has a replication ID and an offset that increments for every byte of the replication stream — together they "identify an exact version of the dataset." When a replica connects it runs PSYNC with its last ID + offset, and one of two things happens:

ResyncWhenWhat happens
Partial Brief disconnect; the primary still has the missed bytes in its backlog buffer. Primary ships just the missing slice of the stream. Cheap.
Full First sync, or the backlog no longer covers the gap. Primary does a BGSAVE → RDB, streams it, then replays buffered writes. Expensive.

Notice the callback to Lesson 0005: a full resync is literally an RDB snapshot (with its fork() cost) streamed to the replica. Diskless replication (repl-diskless-sync) optimizes this — "the child process directly sends the RDB over the wire to replicas, without using the disk as intermediate storage." Redis Docs — Replication

Part 3 — The async trade-off (the heart of it)

By default replication is asynchronous: "low latency and high performance… the natural replication mode for the vast majority of Redis use cases." The primary applies a write and acknowledges it to the client immediately — it does not wait for replicas to confirm. Replication happens in the background. Redis Docs

The window where writes die

Because the ack comes before replicas confirm, "acknowledged writes can still be lost during a failover." Picture it: the client gets OK → the primary crashes a millisecond later → a replica that never received that write is promoted to primary. The write is simply gone. "There is always a window for data loss." This is why Redis is not a strongly-consistent (CP) system. Redis Docs

You can't eliminate the window, but you can narrow it:

ToolWhat it doesGuarantee
WAIT n timeout Blocks until the current connection's writes are acknowledged by ≥ n replicas (or timeout). Best-effort — "does not make Redis a strongly consistent store."
min-replicas-to-write +
min-replicas-max-lag
Primary refuses writes unless ≥ N replicas are connected with lag < M seconds. Restricts the loss window to ~M seconds; still not a hard guarantee.

WAIT is best-effort by design: "it is possible to still lose a write synchronously replicated to multiple replicas." Redis Docs — WAIT

Interview nuance — expiry on replicas (recall from Lesson 0003)

Replicas don't expire keys on their own"they wait for masters to expire the keys," which the primary sends as a synthesized DEL. To avoid handing back a logically-dead value, a replica uses its clock to report the key missing on reads. And once a replica is promoted to primary, "it will start to expire keys independently." Redis Docs

Check yourself

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

By default, when the primary acknowledges a write to the client, replicas have:

Replication is asynchronous by default: the primary acks immediately and propagates in the background. That's why a failover can lose an acknowledged write.

A replica reconnects after a blip and the backlog still covers the gap. It gets a:

PSYNC with a known replication ID + offset that's still in the backlog buffer → the primary ships just the missed slice. A full resync (BGSAVE + RDB) only happens when the backlog can't cover it.

WAIT 2 1000 returning 2 guarantees your write is:

WAIT confirms acknowledgement by N replicas but is best-effort — it "does not make Redis a strongly consistent store." A failover can still lose a write acknowledged by replicas.

To shrink the data-loss window, min-replicas-to-write makes the primary:

If fewer than N replicas (within max-lag) are connected, the primary rejects writes with an error — bounding potential loss to the lag window. It doesn't handle failover itself.

Interleave — a full resync makes the primary produce and stream a:

From Lesson 0005: a full resync runs BGSAVE (fork → RDB), streams the file, then replays buffered writes. Diskless mode streams the RDB over the socket instead of via disk.

Interleave — a replica that hasn't been promoted expires a key by:

From Lesson 0003/here: replicas don't expire keys themselves — they wait for the primary's synthesized DEL, using their clock only to hide a logically-dead key on reads.

Hands-on: build a primary/replica pair

You need two local Redis instances. Start a second on port 6380: redis-server --port 6380 (leave your default 6379 as the primary).

1 · Attach the replica and watch it sync

redis-cli -p 6379 SET k "from-primary"
redis-cli -p 6380 REPLICAOF 127.0.0.1 6379     # make 6380 a replica of 6379
redis-cli -p 6380 GET k                         # -> "from-primary" (synced)
redis-cli -p 6379 INFO replication | grep -E 'role|connected_slaves|master_repl_offset'
redis-cli -p 6380 INFO replication | grep -E 'role|master_link_status|slave_repl_offset'

2 · Prove read-only, then measure replication with WAIT

redis-cli -p 6380 SET x 1        # -> (error) READONLY You can't write against a read only replica.
redis-cli -p 6379 SET y 2
redis-cli -p 6379 WAIT 1 1000    # -> 1  (one replica acknowledged within 1s)
Predict first

Before step 2: what does the replica return for a SET, and why? And if you ran WAIT 2 500 with only one replica attached, what number comes back after 500 ms? Commit, then check. Detach later with REPLICAOF NO ONE (promotes 6380 to primary).

Bring your WAIT 2 500 result and the master_repl_offset vs slave_repl_offset gap to your teacher.

Primary source — read this next

Redis Docs — Replication is the authoritative page: the async model, PSYNC/partial resync, read-only replicas, min-replicas-*, and the data-loss window. Pair it with WAIT for the consistency caveats.