Three Clerks, One Ledger: What 'Agreement' Actually Means
Three servers replicate a key-value store. The client writes x = 5 to server A while a concurrent write x = 7 reaches server B. Network delays reorder the replication traffic, and when the dust settles A believes the key is 5 and B believes it is 7 — reads from different replicas now return different answers, and no amount of timestamping says which write "really" happened. This is the consensus problem: given processes that may crash and a network that may delay or drop messages, get the replicas to agree on one value (or one sequence of values) — and keep agreeing.
The specification splits in two, and every serious discussion uses these names:
| Property | Statement | Violation looks like |
|---|---|---|
| Safety (agreement) | No two correct replicas decide differently; the chosen value never changes afterward | Split brain: one leader commits x=5 in region 1 while another commits x=7 in region 2 |
| Liveness (termination) | A correct value is eventually decided, given enough communication progress | A perfectly consistent system that accepts no writes for an hour |
Safety is never traded: a system that is consistently wrong can be repaired by replaying; a system that is inconsistently correct has lost a fact that no one can reconstruct. Liveness is traded all the time — during a partition, choosing to refuse writes is the correct trade (the PACELC/CAP discussions you will meet return exactly here).
Two theoretical results shape the design space. FLP (1985) proves that in a fully asynchronous system, even one crash-prone process can prevent consensus from terminating — so protocols must assume some timing structure (message timeouts are an assumption, not an implementation detail). Impossibility without a majority is the second: if the network splits a set of replicas so that no majority side can talk to anyone, two sides could each elect a leader and each commit different values — so every correct protocol requires a majority quorum to act at all. Quorums are not a tuning parameter; they are how safety survives partitions.
Raft's contribution is not a new impossibility result but an unusually understandable structure. Where Paxos is a family of arguments about single entries, Raft is deliberately engineered for comprehension — a design goal you can cite in an interview — and its decomposition is the memory anchor:
leader election — one writer at a time, numbered by monotonic terms
log replication — leader appends, followers mirror; the leader alone proposes
safety argument — majorities overlap, so 'committed' entries are on every future
leader's log; elections cannot install an older log as newer
Each of the next two chapters takes one piece. Before that, the framing that keeps Raft in perspective: consensus is the primitive, not the product. Real systems use a Raft-replicated log as the substrate — etcd stores Kubernetes' desired state in it, ZooKeeper drives coordination, Consul holds service registrations — and build sessions, leases, watches, and multi-key transactions on top. When an interviewer asks "what does Raft give you?", the precise answer is: an append-only log that all correct replicas agree on, with the properties that make it usable as a foundation. Knowing what sits above the log is as much a part of the answer as the election rules — and knowing what Raft refuses to promise (we will come back to this) separates users from readers.
Terms, Timeouts, and Overlapping Majorities: How Split-Brain Is Prevented
Split brain is the nightmare: two leaders, each certain of its legitimacy, each committing different values. Raft prevents it with an arithmetic trick and a numbering scheme — no global clock required.
Elections start randomly, not synchronously. Each follower runs an election timeout (typically 150–300 ms, randomized per node so they do not collide). If no heartbeat from a leader arrives before the timeout, the follower increments the term, becomes a candidate, votes for itself, and requests votes from peers. A voter grants at most one vote per term (it remembers the candidate it voted for), and grants it only if the candidate's log is at least as up to date as its own — the rule that stops a stale replica from winning with an old log.
The three mechanisms that collapse split-brain risk:
1. terms are monotonically increasing integers stamped on EVERY RPC — any message
from an older term is ignored, so a delayed packet cannot resurrect yesterday's leader
2. at most one leader per term — a candidate needs a MAJORITY of votes; two majority
sets over n nodes must share at least one member, and that member votes only once
per term ⇒ at most one candidate can reach n/2+1 votes in a given term
3. leaders learn they've been deposed by rejection: a reply carrying a higher term
makes the old leader step down immediately, even if it never saw the new one
Point 2 deserves its arithmetic because it is the safety argument: with 5 nodes, a leader needs 3 votes. Two disjoint sets of 3 cannot exist inside 5 nodes — they overlap — so if any node has already voted in term 4, no rival can collect a second majority of term 4. A split vote (both candidates get 2) simply produces no leader; the randomized timeouts re-trigger, a new term begins, and liveness resumes. Split-brain risk is controlled because only one leader can win a given term's election — and stale leaders are controlled because every RPC carries its term.
The failure story that makes this concrete: a leader in region A is partitioned from the majority. It still believes it is leader — Raft leaders do not voluntarily resign from silence. Clients on its side may accept heartbeats, but the moment it tries to replicate an entry it cannot gather a majority ack, so it cannot commit anything. Meanwhile the majority side times out, holds a new election in a higher term, elects a new leader, and serves reads/writes normally. When the partition heals, the old leader receives a higher-term reply, steps down, and Raft's log-repair rules discard its uncommitted tail. Two leaders briefly existed; only one could ever commit — which is the property that actually matters.
Practical consequences worth citing: election timeouts must be substantially larger than heartbeat intervals (10× is typical) or heartbeats become noise; a minority partition is a read-only-or-dead region by design — clients must be routed or accept stale reads explicitly; and under load, followers that fall behind on disk fsync can timeout spuriously (the well-known Raft liveness wobble in etcd and similar systems), which is why commit latency is dominated by fsync discipline and why production deployments tune election timeout against measured tail disk latency. The election chapter is where Raft's cost becomes visible: safety came from quorums, and quorums mean a partitioned minority cannot serve — a fact every availability design must confront head-on.
Proposal to Committed: The Majority That Makes an Entry Real
Election won; now the log. A client sends SET x=5 to the leader. The leader appends a new log entry — (term 7, index 104, command) — to its private log and fires AppendEntries RPCs to followers in parallel. Each follower appends the entry only after checking consistency: the RPC carries the previous entry's (term, index), and a follower whose log does not match at that position rejects — which triggers the leader to walk its nextIndex backward until the logs realign, overwriting the follower's divergent tail. That rejection-and-truncate loop is how Raft heals a follower that was partitioned while an old leader wrote to it.
A majority quorum is required before entries are considered committed durably. The rule, stated exactly: an entry from the current term is committed when the leader has replicated it to a majority — measured by matchIndex, each follower's highest known-matching index, taking the median of {self + followers} — and the leader applies it to its state machine. Followers learn commit status piggybacked on the next heartbeat/AppendEntries (leaderCommit field), apply the entry, and respond.
t=7 client → leader: SET x=5
leader appends (7,104) ← not committed yet
AppendEntries → f1, f2, f3, f4
f1 ack ✓ f2 ack ✓ ← majority of 5 = 3 including leader ⇒ COMMITTED
f3, f4 lag; healed by next round
leader applies x=5 to state machine, returns success to client
heartbeat carries leaderCommit=104 → followers apply
Follow the crash points, because they are the interview material. Leader dies after appending but before acks: entry is uncommitted — the next leader retries or truncates it; the client, which never got a success, may safely retry (commands carry idempotency context). Leader dies after majority ack but before telling the client: the entry is committed — the new leader has it (majority overlap guarantees any future leader holds every committed entry) and completes the application; the client's timeout resolves via read-your-writes or a status query. Follower crashes mid-append: its persisted tail is either matching or truncated on recovery; Raft's per-index term comparison guarantees the state machine applies the same prefix on every node — replicas may differ in their uncommitted tails, never in what has been applied.
What you get, and what you deliberately do not:
| Guarantee | Detail |
|---|---|
| Linearizable operations (with caveats) | Single leader per term + committed-before-ack; ReadIndex/lease reads avoid the "new leader might be stale" trap |
| Durability | fsync on append before ack — a majority of stable storage, not of memory |
| Cluster membership changes | Joint consensus (old+new majority) so two disjoint majorities cannot form during reconfiguration |
| Not promised: throughput | One leader fsyncs every write: etcd/Consul/ZooKeeper scale to low thousands of writes/sec — that is the design, not a bug |
| Not promised: multi-leader or geo-scale writes | Cross-region quorums multiply RTT into every commit; WAN-tolerant replication is a different layer (see the replication topic) |
The architectural summary to carry out of this topic: Raft buys single-leader agreement through monotonic terms plus overlapping-majority quorums, commits only what a majority has durably stored, and pays with minority unavailability and leader-bound write throughput. When a design brief says "we'll use Raft/etcd for coordination," the checks are: is the write volume within a single fsync-bound leader? What happens to your availability during a minority partition? And what application-level semantics (sessions, leases, watches) will you build on the raw log? Answer those three and you are using consensus as an engineer rather than as a name.
Quiz
1. Two candidates campaign in term 4 in a 5-node cluster, and the network splits voters 2/2 (the fifth is isolated). What happens, and why is that safe?
2. When is a Raft entry considered committed?
3. The leader partitions away from the majority while still believing it is leader. What is correct behavior?
4. A team wants to use etcd (Raft-backed) to store every user's write for a global app. What is the correct architectural response?
Flashcards
Question
Safety vs liveness in consensus, and which is never traded?
Click to reveal answer
Answer
Safety (agreement): no two correct replicas decide differently, and a decided value never changes — violations are unrecoverable split-brain. Liveness (termination): a value is eventually decided if communication progresses — sacrificed during partitions (refusing writes is correct). Safety is never traded; consistent-wrong can be replayed, inconsistently-correct cannot be reconstructed.
Question
Why can only one leader win a given term — the majority-overlap argument?
Click to reveal answer
Answer
A candidate needs n/2+1 votes and each node votes at most once per term. Two majority sets over n nodes must share at least one member; that member's single term-4 vote cannot be cast twice, so at most one candidate can reach majority in that term. Split votes (no majority) produce no leader and are retried in a later, higher term.
Question
How does an entry go from proposal to committed, and what happens at each crash point?
Click to reveal answer
Answer
Leader appends (term,index) → parallel AppendEntries with prev-log check (mismatch ⇒ follower truncates, leader decrements nextIndex) → majority acks (median matchIndex, current term) ⇒ committed, applied to state machine, commit index piggybacked to followers. Crash before majority ack: uncommitted, retried or truncated; after ack before client reply: committed and completed by the new leader — client resolves via idempotency/read.
Question
What does the higher-term mechanism do, in one sentence?
Click to reveal answer
Answer
Every RPC carries its term; a message or reply with a higher term instantly deposes the receiver's leader (or makes a candidate step down), so a partitioned old leader cannot act after a new election even though it never saw the winner — terms are how staleness is detected without a global clock.
Question
Name two things Raft does NOT promise.
Click to reveal answer
Answer
Throughput: one leader fsyncs every write → low thousands of writes/sec (etcd/Consul/ZooKeeper), and more followers add tolerance, not speed. Geo/WAN performance: quorum acks multiply cross-region RTT into each commit — multi-leader and WAN-tolerant replication are separate designs. Also: minority partitions are read-only-or-dead by design; membership changes need joint consensus to avoid two disjoint majorities.
Revision Notes
Key Takeaways
- 1. Consensus splits into safety (never traded) and liveness (yielded during partitions) — quorum requirements come from safety, not performance
- 2. Raft elects one leader per term via majority votes with one-vote-per-term voters; overlapping majorities make two same-term leaders arithmetically impossible
- 3. Terms stamped on every RPC are how a stale leader gets deposed without a global clock — it may exist after losing office, but it can never commit
- 4. Commit = durable majority (median matchIndex in current term) with fsync before ack; majority overlap guarantees every future leader holds all committed entries
- 5. Raft buys agreement with a single fsync-bound leader and minority unavailability — perfect for coordination state, wrong for bulk or geo-distributed writes
Interview Tips
- • 'How does Raft elect a leader?' — randomized timeouts → candidate → one vote per term per node → majority; then give the overlap argument (two n/2+1 sets share a member) as the split-brain answer
- • 'When is an entry committed?' — majority durably replicated, median matchIndex, current-term condition, fsync before ack — then the crash-point analysis: before ack = retry/truncate, after ack = new leader completes
- • 'What happens when the leader is partitioned?' — it cannot commit (no majority), it does NOT resign by silence, the majority side elects a higher-term leader, and on healing the old one steps down and its tail is truncated
- • 'Can we use etcd for our app's write load?' — give the arithmetic: one fsync-bound leader ≈ thousands writes/sec, cross-region quorum multiplies RTT; propose Raft for coordination state and separate replication for bulk data
Cheat Sheet
Raft: Consensus Overview
Problem: replicas agree on one value/sequence despite crashes and reordering. Safety (never disagree, never revert) is absolute; liveness yields during partitions. FLP: async + crash ⇒ termination not guaranteed, so timeouts are assumptions. Majority quorum is required for safety — no majority side, no commits.
Raft's three pieces: leader election · log replication · majority-overlap safety.
Election: randomized 150–300 ms timeouts → candidate, term+1, self-vote · voter: one vote per term, only if candidate log ≥ own · majority (n/2+1) ⇒ leader · higher term in any RPC/reply ⇒ step down · split vote ⇒ next term.
2 disjoint majorities impossible: two n/2+1 sets over n nodes overlap ≥1 node
→ that node's single per-term vote caps leaders at one per term
Replication:
append (term,index) → AppendEntries w/ prev-log check (mismatch ⇒ truncate tail,
walk nextIndex back) → majority of matchIndex (median, current term) ⇒ COMMITTED
→ apply to state machine → leaderCommit piggyback → followers apply
fsync BEFORE ack: majority of stable storage, not memory
Partitioned leader: cannot commit (no majority ack) — exists, never effective;
majority side elects in higher term; on heal, old leader steps down, tail truncated.
Membership: joint consensus (old+new majority simultaneously) blocks two-majority windows.
Budget checks: single fsync-bound leader ⇒ ~10³ writes/sec · cross-region quorum ⇒ RTT×every commit · minority = read-only/stale. Use Raft for coordination state (etcd/K8s, ZooKeeper, Consul locks/leases); bulk data needs partitioned replication (next topics).