Ablation
Switch one of the rules below off, then run it again. A rule that looks redundant makes its case the moment it is gone.
Every non-obvious rule in Raft defends a specific safety property. Turn the rule off and watch the property break — the fastest route to understanding why the rule is there.
Each guard lives in lib/raft/rules.ts and is consulted in exactly one place. That is what makes these switches honest rather than cosmetic: there is no second site quietly still enforcing the rule. Every switch also has a test proving the violation actually occurs.
Unmodified Raft — every rule enforced.
Election restriction
Switch this rule off and the following promise can fail: A record that has been settled never goes missing from any later leader.
A voter refuses a candidate whose log is less up-to-date than its own — comparing last term first, then index. This is what makes Leader Completeness hold.
- Protects:
- Leader Completeness
- Paper section:
- §5.4.1
- In Figure 2:
- RequestVote RPC, receiver rule 2
- Single call site:
- lib/raft/election.ts — handleRequestVote
- Scenario that proves it:
- election-restriction-overwrite
Current-term commit rule
Switch this rule off and the following promise can fail: No two computers ever act on different contents at the same row.
A leader may only mark an entry committed by counting replicas if that entry is from its own term. Older entries commit indirectly. Removing this reproduces Figure 8.
- Protects:
- State Machine Safety
- Paper section:
- §5.4.2
- In Figure 2:
- Rules for Servers, Leaders, final rule
- Single call site:
- lib/raft/commit.ts — advanceCommitIndex
- Scenario that proves it:
- figure-8
AppendEntries consistency check
Switch this rule off and the following promise can fail: If two computers hold the same record at a row, everything above that row is identical too.
AppendEntries carries prevLogIndex and prevLogTerm; the follower rejects on mismatch and the leader walks nextIndex back until the logs agree. Only the term half is ablated here — accepting past the end of a log would punch a hole in it rather than diverge it.
- Protects:
- Log Matching
- Paper section:
- §5.3
- In Figure 2:
- AppendEntries RPC, receiver rule 2
- Single call site:
- lib/raft/replication.ts — handleAppendEntries
- Scenario that proves it:
- log-matching-break
Term increment on candidacy
Switch this rule off and the following promise can fail: There are never two leaders at once in the same round.
Incrementing the term is what makes a campaign a new ballot. Without it, a server that has already voted for someone else campaigns inside the same term and overwrites its own vote.
- Protects:
- Election Safety
- Paper section:
- §5.2
- In Figure 2:
- Rules for Servers, Candidates, rule 1
- Single call site:
- lib/raft/election.ts — startElection
- Scenario that proves it:
- double-candidacy
Step down on higher term
Switch this rule off and the following promise can fail: There are never two leaders at once in the same round.
Any server seeing a higher term adopts it and reverts to follower. Only the role change is ablated, not the term adoption — suppressing both deadlocks elections rather than breaking safety.
- Protects:
- Election Safety
- Paper section:
- §5.1
- In Figure 2:
- Rules for Servers, All Servers, rule 2
- Single call site:
- lib/raft/node.ts — observeTerm
- Scenario that proves it:
- partition-stranded-leader
Persistent votedFor
Switch this rule off and the following promise can fail: There are never two leaders at once in the same round.
votedFor is persistent state and survives a restart. Lose it and one server can vote twice in a term, electing two leaders in it.
- Protects:
- Election Safety
- Paper section:
- §5.2
- In Figure 2:
- State, Persistent state on all servers
- Single call site:
- lib/raft/node.ts — restart
- Scenario that proves it:
- double-vote-restart
Joint consensus
Switch this rule off and the following promise can fail: There are never two leaders at once in the same round.
A membership change passes through a transitional configuration C-old,new, in which agreement requires a majority of the old set *and* of the new one. Without it the cluster switches straight from C-old to C-new — and since there is no instant at which every server switches together, two disjoint majorities can elect two leaders in the same term. That is Figure 10.
- Protects:
- Election Safety
- Paper section:
- §6
- In Figure 2:
- Not in Figure 2 — Figure 10, and §6
- Single call site:
- lib/raft/replication.ts — beginConfigurationChange
- Scenario that proves it:
- membership-change