Replication

Leaderless Replication: Every Replica Accepts Writes

No leader, no failover, no election. A coordinator writes to N replicas and waits for W, reads from R, and repairs what it finds out of date. It removes an entire class of operational problems and replaces them with a permanent, low-grade requirement to reconcile versions.

▶ Run the lab

The question this answers

The question

What does a system look like when no node is special, and what does that cost?

The guarantee — the property claimed, and its scope

Every replica accepts writes; a write acknowledged at level W is present on W replicas at acknowledgement time; a read at level R returns the versions held by R replicas. With strict quorums and R + W > N the read observes a replica that participated in any completed write — but the *value* returned is only well-defined if versions can be ordered, so the system's guarantee is convergence, not recency, unless the application resolves versions correctly.

Everything below is bought to hold this sentence. "Strongly consistent" with no scope attached is a slogan, not a guarantee — read what it actually covers, and what it explicitly does not.

What a node knows — observation versus inference

A replica knows the versions it holds and nothing about the cluster's overall state for a key. A coordinator knows which replicas answered and what they returned; it cannot distinguish "this replica never received the write" from "this replica received it and lost it" from "this replica is about to receive it". Every repair decision is made from an incomplete view, which is why repair must be idempotent and must be safe to run repeatedly.

A node knows its own state and the messages that arrived. Everything else is inference from evidence that was already stale. "B has not replied in five seconds" is knowledge; "B is down" is a decision — and usually the bug.

What guarantee?What does a node know?How does it work?What can fail?How does it fail?Where is coordination?What holds under failure?How does it recover?How would you know?What is the simpler thing?
leaderlessdynamoquorumread repairanti-entropy

What removing the leader actually removes

The gains are operational and they are substantial. No failover: a node dying is a node being unavailable, not a cluster event — there is no election, no promotion window, no split-brain risk, no fencing to get wrong. Uniform write availability: any W reachable replicas can accept a write, so availability degrades smoothly rather than falling off a cliff at the leader. No single write bottleneck: writes for a key can be coordinated by any node.

What is removed along with the leader is the *serialisation point*. Nothing orders concurrent writes to a key any more, which means the conflict problem from Multi-Leader Replication: Accepting Writes in More Than One Place is present here too, permanently and structurally. Leaderless systems are honest about this — that is why version vectors and sibling values are first-class features rather than afterthoughts.

No roles, no election — a node loss is just a node losstypical
c ↔ n1: okc ↔ n2: okc ↔ n3: partitioned — no traffic crossesnode-1 · up — holds v3node-1node-2 · up — holds v3node-2node-3 · down — holds v2 — will be repaired✕ node-3downcoordinator · client · up — any node can play this rolecoordinator▷ clientpartitioned
okpartitioned
  • node-1 — holds v3
  • node-2 — holds v3
  • node-3 — holds v2 — will be repaired
  • coordinator — any node can play this role
What each node believes
  • cbelieves “W=2 satisfied, the write is durable”✓ and it is true
  • cbelieves “node-3 is down”✕ and it is false

Every node above is acting on what it believes. Nothing in the cluster tells the mistaken one that it is mistaken.

Repair is not a background nicety, it is half the system

Because writes only reach W of N and replicas miss updates while unavailable, divergence is continuously produced. Two mechanisms remove it, and both are required. Read repair: when a read finds replicas at different versions, the coordinator writes the newer version back to the laggards. It is cheap and it only covers keys that are read. Anti-entropy: a background process compares replica contents — typically with Merkle trees so the comparison is logarithmic rather than a full scan — and repairs differences regardless of read traffic.

The failure mode that follows is specific and common: a cluster runs with read repair only, because anti-entropy is I/O-expensive and gets disabled during a capacity crunch. Hot keys stay correct. Cold keys diverge permanently, and the divergence is discovered years later during a migration. See Anti-Entropy: Repairing Divergence Nobody Reported and Merkle Trees: Finding the Difference Without Reading the Data.

  • Read repair covers the read set only — it is proportional to read traffic, not to divergence.
  • Anti-entropy covers everything and costs I/O; disabling it converts a self-healing system into one that quietly accumulates errors.
  • Hinted handoff keeps writes available during a node outage by parking them on a substitute — and creates a window where the data is not on the replicas a reader will consult.
  • All three mechanisms must be idempotent, because they run concurrently and repeatedly on incomplete information.

The version problem you cannot delegate

When a read of R replicas returns three different values, something must decide what the answer is. There are exactly three honest options and one dishonest one. Version vectors let the system detect that two versions are genuinely concurrent rather than ordered — this is correct detection. Siblings: return both and let the application merge, which is correct and pushes work upward. CRDTs: choose a data type whose merge is defined, so concurrency is not a conflict at all. The dishonest option is last-write-wins by wall-clock timestamp, which always produces one value, silently discards the other, and is wrong whenever clocks disagree — which is always. See Last Write Wins Is Data Loss You Chose by Default and Clock Skew: The Gap You Cannot Measure From Inside.

This is the tax for removing the leader, and it cannot be paid by configuration. It is a data-model decision made per field, at design time, by people who understand what losing an update would mean for that field.

1read(key, R):
2 responses = send_to_all_replicas(key)
3 wait_for(R responses) # latency = R-th fastest, not the mean
4
5 versions = [r.version_vector for r in responses]
6 newest = dominating(versions) # None if some are concurrent
7
8 if newest is None:
9 # Genuinely concurrent writes. There is no "latest".
10 return siblings(responses) # application merges, or CRDT merges
11 else:
12 # Repair the laggards before returning — asynchronously by default,
13 # synchronously if you want the next read to be non-regressive.
14 for r in responses where r.version < newest:
15 async_write_back(r.node, newest)
16 return newest.value
A leaderless read: gather, order, decide, repair

Key points

  • Removing the leader removes failover, elections and split-brain — and removes the serialisation point that ordered writes.
  • Any W reachable replicas can accept a write, so write availability degrades smoothly instead of falling off a cliff.
  • Divergence is produced continuously, so read repair *and* anti-entropy are both structural requirements, not optimisations.
  • A cluster with read repair but no anti-entropy silently accumulates permanent divergence on cold keys.
  • Concurrent versions must be detected with version vectors and resolved deliberately; timestamp-based resolution loses writes by construction.

The chain, answered

Every field here is required, which is why no lesson in this domain can recommend a design without naming what an operator sees when it fails, what survives the partition, what repairs it afterwards, and the simpler thing to consider first.

How it works
  • A key maps to N replicas, typically via consistent hashing over a ring. See archLinks consistent-hashing.
  • Any node can act as coordinator for an operation on that key; it forwards to all N replicas.
  • A write completes when W replicas acknowledge; a read completes when R replicas respond.
  • The coordinator compares returned versions, returns the dominating value or the concurrent siblings, and issues read repair to replicas found behind.
  • Writes destined for unavailable replicas may be parked on a substitute with a hint, and forwarded when the replica returns (hinted handoff).
  • A background anti-entropy process compares replica state pairwise and repairs differences that reads never touch.
What can fail at the boundary
  • Fewer than W replicas are reachable, so writes at the requested level fail.
  • Concurrent writes produce genuinely unordered versions that no rule can order correctly.
  • Hinted handoffs accumulate and are lost if the substitute node itself fails before forwarding.
  • Anti-entropy is disabled or falls behind and divergence becomes permanent.
  • Ring membership changes and a key's replica set moves while operations are in flight.
How it fails — what an operator sees
  • Value resurrection: a deleted key reappears, because a replica that was down during the delete comes back with the old value and anti-entropy propagates it as if it were an update. This is why deletes need tombstones with a retention period, and why tombstone expiry is a correctness setting rather than a cleanup setting.
  • Permanent silent divergence on cold keys: read repair keeps hot keys correct, anti-entropy is off, and replicas disagree on rarely-read data. Discovered during a migration, years after it started.
  • Sibling explosion: an application that reads siblings and writes back without merging creates more siblings each round, and the operator sees object sizes growing without corresponding user activity until reads start timing out.
  • Silent update loss under last-write-wins: two concurrent writes, resolved by clock, and the write from the node with the lagging clock is gone. No error, and the losing write's author is certain they saved.
  • Latency governed by the slowest quorum member: p99 read latency tracks the R-th fastest replica, so a single degraded node raises the tail for every key it hosts, with no error rate to point at it.
  • Hinted-handoff backlog: after a node returns, a large backlog drains into it while it is also taking live traffic, and the node falls over again.
Where coordination is required
  • Per-operation fan-out and a wait for the W-th or R-th response. There is no agreement between replicas at any point — the coordinator counts, it does not negotiate.
  • No coordination for membership changes in the steady state; the ring is gossiped rather than agreed. See Gossip: Epidemic Spread Instead of Everyone Telling Everyone.
  • Anything requiring agreement — compare-and-set, uniqueness, a counter that must not double-count — is outside what this design provides and needs consensus alongside it. See Do You Actually Need Consensus?.
What still holds under failure
  • Writes remain available as long as any W replicas for the key are reachable, on either side of a partition if W is small enough.
  • With W and R both majorities, the minority side of a partition cannot complete operations, and the system behaves like a majority-quorum system.
  • With W + R ≤ N, both sides of a partition remain available and will diverge, converging after heal via repair — this is the configuration that trades recency for availability explicitly.
How it recovers
  • Detect: monitor divergent-version rate on reads, hinted-handoff depth and age, and anti-entropy completion time per replica pair. All three are direct measures; error rate is not.
  • Contain: throttle hinted-handoff drain so a returning node is not knocked over by its own backlog, and cap sibling counts so an explosion fails loudly rather than silently degrading.
  • Recover: run anti-entropy to completion after any extended node outage rather than trusting read repair to catch up.
  • Reconcile: for keys with siblings, drive an explicit merge pass; siblings that are never resolved are a permanent liability.
  • Verify: compare replica Merkle roots for a sampled key range and alert on mismatch that persists beyond one anti-entropy cycle.
How you would know
  • Divergent-version rate and read-repair rate — the rate at which the cluster is discovering it was out of sync.
  • Hinted-handoff queue depth and oldest hint age, which measure how much data is not where readers expect it.
  • Anti-entropy cycle time per replica pair, and whether it is running at all. This is the metric most often silently zero.
  • Sibling count distribution per key, with an alert on growth — the early signal of a merge bug.
  • Tombstone age relative to the anti-entropy cycle, because expiring a tombstone before every replica has seen the delete is how deleted data returns.
  • Per-replica latency distribution, since R-th-fastest latency is what the client experiences.
When it helps
  • High write-availability requirements where a failover gap is unacceptable and a slightly divergent answer is not.
  • Large clusters with frequent node churn, where leader elections would be a constant background event.
  • Independent-key workloads — session stores, user profiles, shopping carts, sensor data — with no cross-key invariants.
  • Multi-region deployments where writes must be accepted locally in every region.
When it hurts
  • Any invariant spanning keys or requiring uniqueness, ordering, or a limit — the design provides none of these.
  • Teams that will not own conflict resolution as ongoing work, since the system will otherwise default to losing writes silently.
  • Latency-sensitive reads, which pay a fan-out and a tail-latency wait rather than one local answer.
  • Small deployments, where the operational simplicity of a leader plus a tested failover beats the complexity of repair machinery.
Simpler alternatives

No node is special, so repair is half the system

No node is special, so repair is half the system
A write is acknowledged by W replicas and the rest are simply behind. Nothing in the write path fixes that; two background mechanisms do, and a cluster running only one of them accumulates divergence it cannot see.
write acknowledged at
W = 3 of 5
replicas that never saw it
2
converged
step 14
still stale at the horizon
none
step01234567891011121314151617
n1v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2
n2v1v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2
n3v1v1v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2v2
n4v1v1v1v1v1v1v1v1v2v2v2v2v2v2v2v2v2v2
n5v1v1v1v1v1v1v1v2v2v2v2v2v2v2v2v2v2v2
Converged
Converged at step 14 after 10 messages. Every node now serves "v2" — but a reader between step 0 and step 14 could observe any of the intermediate values, and nothing in this model told that reader which one it had.
Removing the leader removes failover, elections and split-brain — and removes the serialisation point that ordered writes. Write availability degrades smoothly instead of falling off a cliff, because any W reachable replicas can take a write. The bill arrives as divergence produced continuously and by design, which is why read repair and anti-entropy are both structural requirements rather than optimisations. And the version problem cannot be delegated: with concurrent writes the replicas hold multiple versions, and resolving them by timestamp loses writes by construction.
simplifiedRepair is modelled as a slow link rather than as read-repair and Merkle-tree exchange in detail; the horizon is a step budget, not a duration. What is faithful is the structural point: a key that nothing reads is repaired by nothing, and stays diverged.

What people believe, and what is true

Claim

Leaderless means no coordination.

Reality

Every operation coordinates a fan-out and waits for a count. What is removed is *agreement*, not communication — and the removed agreement is exactly what would have ordered your writes.

Claim

Read repair keeps the cluster consistent.

Reality

It keeps the keys you read consistent. Without anti-entropy, cold keys diverge permanently, and the divergence is invisible because nothing reads them.

Claim

Deleting a key removes it.

Reality

It writes a tombstone. If the tombstone expires before a replica that was down comes back and gets repaired, the deleted value returns — a real and recurring incident class.

Claim

Leaderless systems are eventually consistent, so they are simpler.

Reality

They are operationally simpler and semantically harder. The complexity moved from failover procedures into the data model, where it is the application's problem rather than the operator's.

Go deeper

Only the levels this lesson can honestly fill — a missing level is a claim nobody had.

Overview

No node is special. Write to W replicas, read from R, repair what disagrees. No failover, but nothing orders concurrent writes.

Practical

Choose W and R deliberately, verify anti-entropy is actually running, make sure concurrency is detected with version vectors rather than clocks, and set tombstone retention longer than any outage you would tolerate. Then decide per field how siblings merge — the system cannot decide that for you.

Advanced

Leaderless replication is what remains when you delete the consensus layer: you keep availability and lose agreement, and every subsequent feature is an attempt to recover a useful fraction of what agreement gave you. Version vectors recover conflict *detection*; CRDTs recover convergence for a restricted class of data types; anti-entropy recovers eventual equality. What none of them recovers is a global order, which is why compare-and-set and uniqueness must be built elsewhere. See What Consensus Actually Solves and Coordination Avoidance: Restructuring the Problem Instead of Paying for It.

Apply it

Reason about this
  • A shopping-cart service on a leaderless store: design the value type so that a concurrent add and remove during a partition converges to an answer a customer would accept.
Interview questions
  • 💬 A key you deleted six months ago has reappeared. Explain how, mechanically.
  • 💬 Why must a leaderless cluster run anti-entropy even though read repair exists?
  • 💬 Your object sizes are growing and nobody is writing more data. What is happening and what is the bug?
  • 💬 What can a leaderless system not give you, no matter how you tune N, R and W?