skip to content

What do the Redis settings `min-replicas-to-write` and `min-replicas-max-lag` actually protect against, and what do they fail to guarantee?

level: middleimportance: should knowfreq 35%

answer

  1. N good replicas acking within S seconds, else refuse writes
  2. Precondition before the write, not an ack after it
  3. NOREPLICAS error; reads keep working
  4. Renamed from min-slaves-* in Redis 5.0
  5. Per-write version = WAIT / WAITAOF

basics

~20 s

They make a primary refuse writes unless at least N replicas were acknowledging it within the last few seconds. That shrinks the window of writes that exist on only one node, but it is a check made before the write, not an acknowledgement after it — so accepted writes can still be lost.

solid answer

~60 s

`min-replicas-to-write N` plus `min-replicas-max-lag S` tell a primary: **stop accepting writes unless at least N replicas have acknowledged me within the last S seconds**. When the condition fails, write commands return an error while reads keep working. What they buy: they prevent the worst case where a primary happily keeps accepting writes with no healthy replica behind it — writes that vanish completely when it dies. They convert silent data loss into a visible, loud write failure, which is usually the trade you want. What they do **not** buy: they are a **precondition**, not a quorum acknowledgement. The primary checks replica liveness from the last ping round, then replies `+OK` as soon as it applies the write locally; replication is still asynchronous, so a write accepted in the final moments before a crash may exist nowhere else. They also say nothing about how far behind the replicas are in *bytes*, only how recently they pinged. For a per-write guarantee you need `WAIT numreplicas timeout` after the write, and even that is not a rollback.

code

text · 19 lines
text
# redis.conf on the primary
min-replicas-to-write 1
min-replicas-max-lag 10

# with no good replica connected, writes are refused:
> SET k v
(error) NOREPLICAS Not enough good replicas to write.
> GET k          # reads are unaffected
"old-value"

# what the primary sees per replica (lag in seconds):
> INFO replication
connected_replicas:1
replica0:ip=10.0.2.12,port=6379,state=online,offset=88213,lag=0

# per-write acknowledgement instead of a precondition:
> SET order:1 paid
> WAIT 1 100      # blocks up to 100ms
(integer) 1       # number of replicas that acked this offset

go deeper

for a junior

State the basic behaviour: the primary stops accepting writes if it does not have enough replicas keeping up, and reads still work.

for a middle

Explain that the check uses replica acknowledgement age, that it is a precondition rather than a commit, and that it trades availability for a smaller loss window.

for a senior

Pick concrete values with headroom, explain the false-positive sources for a tight max-lag, and contrast the setting with WAIT/WAITAOF for per-write assurance.

for a principal

Frame it as a policy decision per data class — which shards should go read-only rather than accept unreplicated writes — and combine it with the cluster's majority rule and the application's behaviour when writes are refused.

## What the settings do mechanically Every connected replica sends `REPLCONF ACK <offset>` to its primary about once a second. The primary tracks, per replica, when it last heard such an ack. `min-replicas-max-lag S` defines "good": a replica whose last ack is younger than S seconds counts as good. `min-replicas-to-write N` says how many good replicas the primary must see. If the count of good replicas drops below N, the primary starts rejecting write commands with an error such as `NOREPLICAS Not enough good replicas to write`, while continuing to serve reads. Both were named `min-slaves-to-write` / `min-slaves-max-lag` before Redis 5.0; the old names still work as aliases. They apply to standalone and Sentinel-managed primaries as well as to cluster primaries. ## What they genuinely protect against The scenario is: your only replica has been down for an hour (crashed, network-isolated, restarted into a bad state) and nobody noticed. The primary keeps accepting writes; every one of them exists on exactly one machine. When that machine dies, all of it is gone, and if a replica is later promoted it silently rewinds to an hour-old state. With `min-replicas-to-write 1` the primary refuses writes as soon as it is alone. The application sees errors immediately, monitoring lights up, and the operator learns about the missing replica within seconds instead of during the outage. That is an **availability-for-durability trade**, and it is the right default for anything where a silent rewind is worse than a visible error. It also shrinks the exposure window during failover: if the primary was refusing writes while unreplicated, there are fewer unreplicated writes to lose when a replica is promoted. ## What they do not guarantee 1. **Not a synchronous commit.** The check happens *before* the command is executed; the reply is still sent as soon as the primary applies it locally. A write accepted at T can be lost if the primary dies at T + 1 ms before propagation. Anyone who describes these settings as "synchronous replication" or "quorum writes" has the model wrong. 2. **Liveness, not currency.** `max-lag` measures the age of the last acknowledgement, not the replica's byte offset. A replica can be acking promptly while lagging behind in applied data — for instance while it is loading a large dataset or its output buffer is congested. 3. **No protection against promoting a stale replica.** Cluster failover picks the eligible replica with the best replication offset, but if all replicas lag, that is still the best of a bad set. These settings limit how far the primary is allowed to run ahead of *some* replica; they do not pin the promoted one. 4. **No effect on reads.** Reads continue during the refusal, including from replicas, so stale reads are unaffected. ## Interaction with Redis Cluster In cluster mode this is a *per-shard* setting layered on top of the cluster's own rule that a primary unable to reach a majority of primaries stops accepting writes after `cluster-node-timeout`. The two mechanisms guard different things: the majority rule guards against a partitioned primary accepting writes that will be discarded, while `min-replicas-to-write` guards against an unreplicated primary accepting writes that will be lost outright. ## Choosing values - `min-replicas-to-write 1`, `min-replicas-max-lag 10` is a reasonable starting point for a shard with two replicas: the primary refuses writes only when it is genuinely alone, and 10 s is comfortably above the 1 s ack cadence so ordinary jitter does not trip it. - Setting N equal to the number of replicas is fragile: a single replica restart, a `BGSAVE`-induced stall, or a rolling upgrade makes the shard read-only. Keep at least one replica of headroom. - Setting `max-lag` to 1 s invites false positives from GC-like stalls, fork pauses and network jitter. - Never enable it on a pure cache where errors are worse than loss — there the correct posture is the opposite. ## The per-write tool When an individual write genuinely must reach replicas, use `WAIT numreplicas timeout` immediately after it: it blocks until that many replicas have acknowledged the primary's current offset, or the timeout expires, and returns the count actually reached. It does not roll back if the count is short — your code must decide what to do — and it is a client-driven wait, not a commit protocol. Redis 7.0 added `WAITAOF` for acknowledgement of local and replica AOF fsyncs, which is the closest Redis gets to a durability barrier.

  • Does setting min-replicas-to-write 1 mean an acknowledged write is safely on a replica?
    No. The setting is evaluated before the command runs and only asks whether enough replicas were acknowledging recently; the reply is still sent as soon as the primary applies the write locally, and propagation remains asynchronous. A write accepted moments before the primary crashes can still exist nowhere else. Per-write assurance requires WAIT after the write, and even then WAIT reports a count rather than rolling anything back.
  • What is the risk of setting min-replicas-to-write equal to the number of replicas?
    Any single replica becoming unavailable — a restart, an upgrade, a stall while it forks for a snapshot, or a brief network problem — makes the shard reject all writes. You have converted a redundancy mechanism into a single point of failure for availability. Keep at least one replica of headroom so routine maintenance does not take writes offline.

saying these in an interview costs you the question

  • Describing these settings as synchronous or quorum replication
  • Believing an accepted write is guaranteed to be on N replicas
  • Setting min-replicas-to-write equal to the replica count and being surprised by read-only outages during upgrades
  • Thinking max-lag measures byte lag rather than the age of the last acknowledgement
  • Enabling it on a pure cache where write errors hurt more than losing a value

context