Consensus And Quorums
Purpose
Consensus is a set of processes agreeing on one value with safety despite modeled crashes,
loss and delay; progress additionally needs a quorum and timing assumptions such as eventual
synchrony. Consensus can order a replicated log used for grants and configuration, but is not
itself a lock or lease. Leases, locks, role election and shard ownership have distinct contracts;
not every election uses a lease, and ownership can change dynamically. Route external stale-owner
safety to distributed-locks-and-leases and role lifecycle to leader-election.
The failure this prevents is a coordination store used as a traffic-scaled database. etcd,
ZooKeeper and Consul are replicated metadata/coordination stores with different read contracts;
writes pass through a leader/quorum log and durable storage, often batched/pipelined. Business
rows, a work queue or a per-request job table in one
makes every business write a consensus decision — and puts the store's availability in series
with the service's, which is the arithmetic in failure-models.
Workflow
This skill is protocol-level and has no Java language minimum. For a Java integration inspect
the project toolchain, resolved client version, deployed server version, read options and
durability/failover policy. Product references here cover etcd 3.6 and ZooKeeper 3.8.4;
verify Consul modes against the deployed version. Do not upgrade Java or the store to match
a reference. Missing membership, durability or read-contract evidence prevents a safety claim.
- Ask whether anything must be agreed at all. Most designs that reach for consensus need a
single-key conditional write, which the database already provides. Consensus is for
decisions that must be single-valued fleet-wide and survive their author's death.
- Size the cluster from
f, the number of simultaneous failures you tolerate. 2f+1
voting members with majority quorums tolerate f, assuming the survivors can communicate
and retain required durable state. Exclude learners/observers from the voter count.
- Place voters and price the commit path. Account for leader routing, network RTT,
replication, durable-log latency, batching and the fastest quorum. Placement sets correlated
failure tolerance and latency (
references/quorum-arithmetic.md).
- Decide, in writing, what each side of a partition does. The minority side cannot form a
quorum and therefore cannot make progress; that is the design working, not an outage to
engineer around. CAP itself is
consistency-models.
- Choose product-specific read semantics per call site. etcd linearizable and serializable
reads differ; ZooKeeper member-local reads are not linearizable. Measure the actual path.
- Keep traffic-proportional business data out and avoid synchronous coordination per request. Cache the decision locally,
with a defined behaviour for "store unreachable" (
references/coordination-stores.md).
- Exercise failure behaviour in an isolated cluster. With
2f+1 voters, remove f and
assert eventual write progress within the recovery budget. Remove f+1 and verify newly
initiated writes cannot be acknowledged as committed without a quorum. In-flight writes
may have committed before disruption; timeouts retain unknown outcomes. Test each minority
read/fail-fast policy and restore the fixture afterward.
Decision block
Use a consensus-backed coordination store when:
- a decision must be single-valued fleet-wide (who holds a role, which shard-map version is
current, which config generation is active) and must survive the death of its author
- decisions are small and their measured rate/retention fit the product's tested envelope
- you can tolerate the store being unavailable for the duration of an election
Avoid it when:
- the data is application state, an event stream, or anything whose volume grows with traffic
- the write rate scales with request rate — every write is a majority round trip
- it would sit on the synchronous request path with no cached fallback, making its availability
a hard multiplier on yours
Prefer instead when:
- the decision is a single-key compare-and-swap and the existing database's atomicity,
durability and failover contract meet the need: use its conditional write rather than
adding another coordination system; a unique constraint alone does not prove HA consensus
- work can be partitioned so each key has one owner by assignment (sharding-and-partitioning),
which needs no agreement at request time at all
- the work is idempotent and safe on every replica (idempotency) — the cheapest coordination
is none
Rules
- FLP: no deterministic algorithm guarantees termination of consensus in a fully asynchronous system where even
one process may crash. A timeout suspects failure; it does not distinguish a crash from
arbitrary delay or invalidate the theorem. Practical progress depends on additional timing,
failure-detector or randomized-progress assumptions. Correct protocols preserve safety under their stated crash/storage assumptions and become live
under stronger timing/quorum assumptions. Byzantine behavior, disk corruption, clock misuse,
misconfiguration and implementation bugs are outside that shorthand.
2f+1 tolerates f crash failures because any two majorities of 2f+1 share at least one
node, so a later quorum always meets a member of the earlier one under fixed membership.
Common partially synchronous Byzantine quorum protocols use 3f+1 with 2f+1 quorums;
Byzantine bounds depend on the model and protocol and are outside this skill's crash model.
- An extra even-numbered voter does not increase majority crash-failure tolerance: four and three
both tolerate one unavailable voter; six and five both tolerate two. It can still be a
transitional reconfiguration or meet a placement/read requirement, so compare that purpose
with its larger quorum and replication cost.
- Adding voters increases replication work and changes the required quorum. Commit latency
includes the fastest satisfying durable quorum, leader work, routing and queueing; topology
and batching matter. More voters do not shard a single log, but latency/throughput changes
must be measured rather than asserted universally.
R + W > N makes read and write sets intersect within the same fixed replica set.
Observing an acknowledged write also requires durable replicas and a valid version/conflict
protocol. It does not by itself make reads linearizable: concurrent writes may be partially applied, and a
sloppy quorum accepting hinted replicas breaks the intersection outright. Intersection is a
necessary condition, not a consistency model.
- Raft elects at most one leader per term. A leader can directly commit an entry from its
current term once durably replicated to a majority; committing it also commits earlier
entries in that prefix. An old-term entry merely appearing on a majority is not sufficient
(Raft section 5.4.2). A partition can leave an obsolete leader active in a different term.
- A Raft term fences protocol messages inside that Raft group: followers reject stale terms and
an isolated old leader cannot commit without a quorum. A term/revision does not automatically
fence writes to an external database, object store or device; that resource must compare a
monotonically increasing grant token, and the token must distinguish each ownership grant.
- Watch guarantees are product-specific. etcd orders unique events by revision and supports
resume within retained history, but watches are not linearizable and compaction forces resync.
ZooKeeper standard watches are one-shot and can miss intermediate changes between re-registration;
its persistent watch modes have a different lifecycle, not durable broker semantics.
Consumers checkpoint versions and rebuild state on gaps/compaction instead of assuming a
generic notification contract.
- Lease/session authority follows the store's expiry protocol, not the holder's belief:
the holder can believe it holds a grant the cluster has already regranted. Do not assume a
synchronized ensemble clock. That gap is
distributed-locks-and-leases.
- A compare-and-swap has three outcomes. An acknowledged failed comparison is "rejected";
a timeout means unknown — it may have applied with only the response lost. Reconcile the
unique attempt with supported strong reads/history; retain unknown if evidence is ambiguous
(
failure-models). A matching holder name alone does not establish current authority.
Deliver the voter/failure-domain map, quorum arithmetic, commit/read assumptions, unknown-outcome
policy and bounded failure tests. A successful kill test is evidence for that topology and run,
not proof of consensus correctness or external fencing.
References
- Quorum arithmetic and placement —
2f+1 and R + W > N
worked through with examples, the even-node result, cluster sizing, cross-AZ and cross-region
placement with the latency cost per decision, and what each side of a partition can do. Read
when choosing a cluster size, adding a node, or spreading voters across failure domains.
- Coordination stores in practice — the primitives
(compare-and-swap, leases with TTL, watches), the operations these stores are wrong for,
their throughput and failure characteristics, watch semantics, and a decision table for
behaviour when the store is unreachable. Read before putting anything into etcd, ZooKeeper or
Consul, or when a coordination store appears on a request path.
Primary sources
1---2name: consensus-and-quorums3description: Crash-fault consensus and quorum reasoning: FLP, safety versus liveness, majority 2f+1, R + W > N intersection and its limits, voter/failure-domain placement, Raft terms and why external fencing still requires resource enforcement, plus the differing read/watch contracts of etcd, ZooKeeper and Consul. Use when a cluster size is being chosen, when nodes are spread across AZs or regions, when application data or a queue is being put in etcd or ZooKeeper, when a coordination store sits on the request path, when a watch is treated as a delivery guarantee, or when a fourth node is proposed for redundancy. Does not cover CAP and the model ladder (consistency-models), mutual exclusion built on top (distributed-locks-and-leases), electing a singleton worker (leader-election), or the fault model itself (failure-models).4---56# Consensus And Quorums78## Purpose910Consensus is a set of processes agreeing on **one value** with safety despite modeled crashes,11loss and delay; progress additionally needs a quorum and timing assumptions such as eventual12synchrony. Consensus can order a replicated log used for grants and configuration, but is not13itself a lock or lease. Leases, locks, role election and shard ownership have distinct contracts;14not every election uses a lease, and ownership can change dynamically. Route external stale-owner15safety to `distributed-locks-and-leases` and role lifecycle to `leader-election`.1617The failure this prevents is a coordination store used as a traffic-scaled database. etcd,18ZooKeeper and Consul are replicated metadata/coordination stores with different read contracts;19writes pass through a leader/quorum log and durable storage, often batched/pipelined. Business20rows, a work queue or a per-request job table in one21makes every business write a consensus decision — and puts the store's availability in series22with the service's, which is the arithmetic in `failure-models`.2324## Workflow2526This skill is protocol-level and has no Java language minimum. For a Java integration inspect27the project toolchain, resolved client version, deployed server version, read options and28durability/failover policy. Product references here cover etcd 3.6 and ZooKeeper 3.8.4;29verify Consul modes against the deployed version. Do not upgrade Java or the store to match30a reference. Missing membership, durability or read-contract evidence prevents a safety claim.31321. **Ask whether anything must be agreed at all.** Most designs that reach for consensus need a33 _single-key conditional write_, which the database already provides. Consensus is for34 decisions that must be single-valued fleet-wide and survive their author's death.352. **Size the cluster from `f`, the number of simultaneous failures you tolerate.** `2f+1`36 voting members with majority quorums tolerate `f`, assuming the survivors can communicate37 and retain required durable state. Exclude learners/observers from the voter count.383. **Place voters and price the commit path.** Account for leader routing, network RTT,39 replication, durable-log latency, batching and the fastest quorum. Placement sets correlated40 failure tolerance and latency (`references/quorum-arithmetic.md`).414. **Decide, in writing, what each side of a partition does.** The minority side cannot form a42 quorum and therefore cannot make progress; that is the design working, not an outage to43 engineer around. CAP itself is `consistency-models`.445. **Choose product-specific read semantics per call site.** etcd linearizable and serializable45 reads differ; ZooKeeper member-local reads are not linearizable. Measure the actual path.466. **Keep traffic-proportional business data out and avoid synchronous coordination per request.** Cache the decision locally,47 with a defined behaviour for "store unreachable" (`references/coordination-stores.md`).487. **Exercise failure behaviour in an isolated cluster.** With `2f+1` voters, remove `f` and49 assert eventual write progress within the recovery budget. Remove `f+1` and verify newly50 initiated writes cannot be acknowledged as committed without a quorum. In-flight writes51 may have committed before disruption; timeouts retain unknown outcomes. Test each minority52 read/fail-fast policy and restore the fixture afterward.5354## Decision block5556```text57Use a consensus-backed coordination store when:58- a decision must be single-valued fleet-wide (who holds a role, which shard-map version is59 current, which config generation is active) and must survive the death of its author60- decisions are small and their measured rate/retention fit the product's tested envelope61- you can tolerate the store being unavailable for the duration of an election62Avoid it when:63- the data is application state, an event stream, or anything whose volume grows with traffic64- the write rate scales with request rate — every write is a majority round trip65- it would sit on the synchronous request path with no cached fallback, making its availability66 a hard multiplier on yours67Prefer instead when:68- the decision is a single-key compare-and-swap and the existing database's atomicity,69 durability and failover contract meet the need: use its conditional write rather than70 adding another coordination system; a unique constraint alone does not prove HA consensus71- work can be partitioned so each key has one owner by assignment (sharding-and-partitioning),72 which needs no agreement at request time at all73- the work is idempotent and safe on every replica (idempotency) — the cheapest coordination74 is none75```7677## Rules7879- **FLP: no deterministic algorithm guarantees termination of consensus in a fully asynchronous system where even80 one process may crash.** A timeout suspects failure; it does not distinguish a crash from81 arbitrary delay or invalidate the theorem. Practical progress depends on additional timing,82 failure-detector or randomized-progress assumptions. Correct protocols preserve safety under their stated crash/storage assumptions and become live83 under stronger timing/quorum assumptions. Byzantine behavior, disk corruption, clock misuse,84 misconfiguration and implementation bugs are outside that shorthand.85- `2f+1` tolerates `f` crash failures because any two majorities of `2f+1` share at least one86 node, so a later quorum always meets a member of the earlier one under fixed membership.87 Common partially synchronous Byzantine quorum protocols use `3f+1` with `2f+1` quorums;88 Byzantine bounds depend on the model and protocol and are outside this skill's crash model.89- An extra even-numbered voter does not increase majority crash-failure tolerance: four and three90 both tolerate one unavailable voter; six and five both tolerate two. It can still be a91 transitional reconfiguration or meet a placement/read requirement, so compare that purpose92 with its larger quorum and replication cost.93- Adding voters increases replication work and changes the required quorum. Commit latency94 includes the fastest satisfying durable quorum, leader work, routing and queueing; topology95 and batching matter. More voters do not shard a single log, but latency/throughput changes96 must be measured rather than asserted universally.97- `R + W > N` makes read and write sets intersect within the same fixed replica set.98 Observing an acknowledged write also requires durable replicas and a valid version/conflict99 protocol. It does **not** by itself make reads linearizable: concurrent writes may be partially applied, and a100 sloppy quorum accepting hinted replicas breaks the intersection outright. Intersection is a101 necessary condition, not a consistency model.102- Raft elects at most one leader per term. A leader can directly commit an entry from its103 **current term** once durably replicated to a majority; committing it also commits earlier104 entries in that prefix. An old-term entry merely appearing on a majority is not sufficient105 (Raft section 5.4.2). A partition can leave an obsolete leader active in a different term.106- A Raft term fences protocol messages _inside that Raft group_: followers reject stale terms and107 an isolated old leader cannot commit without a quorum. A term/revision does not automatically108 fence writes to an external database, object store or device; that resource must compare a109 monotonically increasing grant token, and the token must distinguish each ownership grant.110- **Watch guarantees are product-specific.** etcd orders unique events by revision and supports111 resume within retained history, but watches are not linearizable and compaction forces resync.112 ZooKeeper standard watches are one-shot and can miss intermediate changes between re-registration;113 its persistent watch modes have a different lifecycle, not durable broker semantics.114 Consumers checkpoint versions and rebuild state on gaps/compaction instead of assuming a115 generic notification contract.116- Lease/session authority follows the store's expiry protocol, not the holder's belief:117 the holder can believe it holds a grant the cluster has already regranted. Do not assume a118 synchronized ensemble clock. That gap is `distributed-locks-and-leases`.119- A compare-and-swap has three outcomes. An acknowledged failed comparison is "rejected";120 a timeout means unknown — it may have applied with only the response lost. Reconcile the121 unique attempt with supported strong reads/history; retain unknown if evidence is ambiguous122 (`failure-models`). A matching holder name alone does not establish current authority.123124Deliver the voter/failure-domain map, quorum arithmetic, commit/read assumptions, unknown-outcome125policy and bounded failure tests. A successful kill test is evidence for that topology and run,126not proof of consensus correctness or external fencing.127128## References129130- [Quorum arithmetic and placement](references/quorum-arithmetic.md) — `2f+1` and `R + W > N`131 worked through with examples, the even-node result, cluster sizing, cross-AZ and cross-region132 placement with the latency cost per decision, and what each side of a partition can do. Read133 when choosing a cluster size, adding a node, or spreading voters across failure domains.134- [Coordination stores in practice](references/coordination-stores.md) — the primitives135 (compare-and-swap, leases with TTL, watches), the operations these stores are wrong for,136 their throughput and failure characteristics, watch semantics, and a decision table for137 behaviour when the store is unreachable. Read before putting anything into etcd, ZooKeeper or138 Consul, or when a coordination store appears on a request path.139140## Primary sources141142- [Raft paper](https://raft.github.io/raft.pdf)143- [FLP impossibility result](https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf)144- [etcd API guarantees](https://etcd.io/docs/v3.6/learning/api_guarantees/)145- [ZooKeeper consistency guarantees](https://zookeeper.apache.org/doc/r3.8.4/zookeeperInternals.html)