Build Raft — consensus you can defend (12 scenes)
Scene 05 · Commit, and the Figure 8 trap
An entry is committed when stored on a majority AND at least one entry from the leader's CURRENT term is replicated to a majority. The second clause is the one that prevents Figure 8 — without it, a 'committed' entry can be overwritten by a future leader.
Previously

Last scene you learned how a leader copies its log onto followers and how the consistency check keeps every follower's prefix matching the leader's. Once an entry is on a majority of servers, the obvious next question is: when is it safe for the application to ACT on that entry — to charge the credit card, print the order, advance the bank balance?

Scene 05
Commit, and the Figure 8 trap
Diagram
A 4-panel storyboard mirroring paper Figure 8. Five servers (S1..S5) stacked top to bottom; each panel shows a short log strip per server, and the entry sitting at log index 2 is highlighted across every panel. Watch the COLOR of that index-2 entry change across panels — the color flip is the bug. Panel (c) carries a `commit?` badge under index-2 that lights up based on the manipulate toggles; the fork panel shows EITHER (d1), the unsafe future where S5 overwrites the 'committed' entry, OR (d2), the safe future where S1 first commits a new entry from its own term.
FIGURE 8 — §5.4.2(a)S1 is leader for…★ S1S1T2i1t1i2t2S2·T2i1t1i2t2S3·T1i1t1S4·T1i1t1S5·T1i1t1current-term commit rule: OFFterm colors: t2 teal · t3 amber · t5 roseleadercrashedidx-2 highlight ring (same entry across panels)
index-2 sits on S1 and S2 only — a minority →
Here's a sneaky failure that almost made Raft incorrect. Watch what happens when we use a naive 'replicated to a majority = safe' rule. The story plays out across three panels you'll see appear one after another. **Panel (a):** S1 is the leader for term 2. It writes a new entry at log index 2 and manages to copy it to S2 before anything bad happens. Two servers out of five have the entry. That is a minority — not enough to call the entry safe yet. **Panel (b):** S1 crashes. S5 wakes up and runs an election for term 3. S3, S4, and S5 all have only the term-1 prefix in their logs, so from each other's point of view they're equally up-to-date — S5 wins with votes from S3, S4, and itself. S5 is now leader. It writes its OWN entry at index 2 (a different one, for term 3) — into its own log. Then S5 crashes too, before telling anyone. **Panel (c):** S1 comes back to life. It runs an election for term 4 and wins — S1 still has the term-2 entry at index 2, which is more up-to-date than what S3 has, so S1 gets votes from itself, S2, and S3. As leader, S1 continues the work it never finished and copies its term-2 entry out to S3. Now three servers out of five — S1, S2, S3 — hold that index-2 entry. A majority. With a naive rule of 'on a majority = safe,' S1 would now mark this entry committed and tell the application to act on it. In the next phase you'll see why that would be a disaster.
Implementation
Leader.tryAdvanceCommit (naive — BUGGY)
the version that Figure 8 breaks
1def tryAdvanceCommit():
2 # for every index N > commitIndex, count replicas
3 for N in range(commitIndex + 1, log.lastIndex() + 1):
4 replicas = 1 # leader itself
5 for f in followers:
6 if matchIndex[f] >= N:
7 replicas += 1
8 if replicas > len(cluster) / 2:
9 commitIndex = N # advances on ANY entry
Follower.handleAppendEntries (truncation step)
the mechanism panel (d1) uses to overwrite idx=2
1def handleAppendEntries(req):
2 # … term and consistency checks elided …
3 # step (3): if an existing entry conflicts with a new
4 # one (same index, different term), delete it AND
5 # everything after it, then append the new entries
6 for i, e in enumerate(req.entries):
7 idx = req.prevLogIndex + 1 + i
8 if idx <= log.lastIndex() and log[idx].term != e.term:
9 log.truncateFrom(idx) # this is how (d1) wipes idx=2
10 if idx > log.lastIndex():
11 log.append(e)