Interactive course · about 8 hours

Raft and Consensus

Five computers are asked to keep the same list. Any of them can stop working at any moment, and the wires between them can go quiet for a while and then come back. Somehow the five must never disagree about what is on the list. Raft is the set of rules that gets that done. It is short enough to build one piece at a time and watch every piece work.

How this works

There is one set of Raft rules built into this page, and every lab is a view onto it. The same election code, the same repair code and the same counting rule run whether you are stepping one moment at a time by hand or hammering a five-machine cluster with crashes. Nothing on these pages is a number typed into the prose: the clusters are really built, really run, and really checked.

What you need to know first

No maths beyond adding and halving, and no programming. Two steps ask you to write a short rule in code, and both give you the shape to fill in and explain every word of it. If you have done Distributed Consistency you will recognise the failures being simulated here, but this course introduces each one again from the beginning.

The steps

Step 1

One log, many machines, and no disagreement ever

Start with the job, because the rest of the course is one long answer to it. A bank keeps your balance on a computer. One computer is not enough: it can catch fire, or its power can fail, and your money should not depend on a single box in a single room. So the bank runs several computers, and a group of computers working together as one service is called a cluster.

None of these machines stores your balance as a number. Each one stores the log: a numbered list of the commands that have happened, in order, where nothing is ever changed once it is written down. +50 means money came in. -30 means money went out. Each line of the log is called an entry, and its number is its index: entry 1, entry 2, entry 3. To find the balance, a machine starts at 100 and applies every entry in order.

Why keep a list of changes instead of just keeping the number?

Because a number on its own cannot be checked, repaired or compared. If two machines hold the number 120 and 90, there is no way to work out which one is right. If they hold lists of commands, you can put the lists side by side and find the exact entry where they stopped agreeing.

A list of changes has another property that matters more here. Two machines that hold the same list and apply it in the same order must arrive at the same answer, every time, with no coordination at the moment of asking. So the whole problem of keeping many machines in agreement collapses into one question: can we keep their logs identical? Everything else follows from that.

So the goal is exact: keep the logs on all the machines identical, forever, while machines crash and the network misbehaves. Below, nothing enforces that yet. You are the network, and you decide who hears what.

Lab 1 · Three machines, no rules
Try this firstPress Send to A twice, then press Send to all three once. The three logs now hold different commands, and the line underneath names the first entry where they differ and reports what each machine thinks the balance is. The small number in each box is that entry's index, its place in the list.
Notice: there is no way to tell which balance is the real one. The machines are not broken and nobody made a mistake. Each faithfully applied what it was given. Press Start over and try sending every command to all three each time, which is the only pattern that keeps them equal.
What do +50, -30 and x2 actually do?

They are the commands in this course's toy service, and they mean what they look like. Starting from 100, a log of +50 then -30 gives 120. An x2 doubles the balance, which is not something a real bank does, but it is here on purpose: doubling is the command that makes order matter.

Real clusters copy real commands, and this is the honest shape of it. The program behind a shop's website copies "set row 91 to this value". A service that stores files copies "put this piece of the file at this position". The machinery in this course does not care what the commands mean, only that everybody holds the same ones in the same order.

Lab 2 · The same commands, in a different order
Try this firstPress Swap the first two. Both machines still hold the same three commands, and the balance on the right changes on B only. Press Swap the last two as well, then Put them back.
Notice: holding the same commands is not enough. x2 then -30 is not the same as -30 then x2, because doubling a smaller number gives less. So the target is stricter than it first looked: the same entries, at the same indexes, in the same order, on every machine.
Why five machines? Why not two, or a hundred?

Two is the worst number. When two machines disagree, there is no way to break the tie, and if one goes quiet the other cannot tell whether it has crashed or whether the wire has broken. Everything in this course rests on being able to gather more than half, and more than half of two is two, so a two-machine cluster stops working the moment anything goes wrong.

Odd numbers are used for that reason, and small odd numbers because every machine has to be sent every entry. Three survives one failure and five survives two, which is why five is the usual answer. A hundred machines would survive forty-nine failures and would be slow at everything, because more than half of a hundred is fifty-one replies to wait for.

Two machines each hold exactly the same three commands, but one of them received them in a different order. What can you say about the two balances?
They can differ. Order sometimes matters and sometimes does not, which is exactly why "the same order" has to be a rule rather than a hope. +50 then -30 gives the same answer either way round, because adding and subtracting can be done in any order. Put x2 in the list and the order decides the money. A rule that only sometimes matters is the most dangerous kind, because a cluster can look fine for months and then quietly get one wrong.
Step 2

Number the stretches of time, so a stale leader shows up

To keep the logs identical, only one machine may decide what goes in them, and that machine is called the leader. The others are followers: they take what the leader sends and write it down. A machine that is trying to become leader is a candidate. Every machine is in exactly one of those three roles at any moment. It can change role in either direction.

Leaders do not last forever. One crashes, another is elected, and later the first one comes back still believing it is in charge. So the cluster needs a way to tell an old leader from the current one. It cannot use the clock, because clocks on different machines disagree, and a machine has no way to know its own clock is wrong. Instead Raft counts. Time is divided into numbered stretches called terms: term 1, term 2, term 3, each with at most one leader. Every message carries the term number of the machine that sent it.

What is a term, exactly, and what makes it go up?

A term is just a number that each machine keeps and never lowers. It goes up in one situation: a machine gives up waiting to hear from a leader and decides to try to become leader itself. It adds one to its own term and asks for votes in that new term. So terms count leadership attempts, not seconds, and a term can last a millisecond or a month.

Two rules make the number useful. A machine that hears a term higher than its own adopts that number at once and drops back to being a follower, because a higher term means it has missed something. A machine that hears a term lower than its own refuses the message, because the sender is out of date and does not know it yet.

Two kinds of message travel between machines. One asks for a vote, which is Step 3. The other carries log entries and is called an append, which is Step 5. What matters now is only the number stamped on the outside, and the rule for reading it.

Lab 3 · One message, and what the number does to it
Try this firstLeave a vote request stamped term 2 chosen, press It refuses, and stays in term 4, then press Deliver it. Machine D really receives that message, and the before and after lines show what it did with it. Then try the message stamped term 7.
Notice: the term 7 request pushes D from term 4 to term 7 before D has any idea what happened while it was away. That is the whole trick. A machine does not need to know the history it missed. It only needs to know that somebody is further ahead, and one number tells it.
Why not just use the time of day on each machine?

Because a clock is measured and a term is counted. Measuring involves error: a machine's clock runs slightly fast or slow, gets corrected by a jump, or was set wrong when it started. Two machines a metre apart can disagree by a whole second, and neither can tell which of them is the odd one.

Counting has no error. Nothing is being read off a dial. The number was 4 and somebody added one, so it is 5, and every machine that hears about term 5 knows term 4 is over. The cost is that a term number says nothing about how long anything took. It only puts events in order, and order is all these rules need.

Lab 4 · A clock that lies, next to a number that cannot
Try this firstDrag the slider to the right, past 20. The table keeps the same real events and only changes what B's clock said about its own. Watch the line underneath change its verdict about which write came last.
Notice: the clock is right until it is not, and nothing announces the moment it flips. There is no reading you could take that would tell you. The term row never flips, because the term was not measured off a clock. It was handed out in order by machines that agreed to count.
Why does a reply carry a term as well?

Every message carries one, in both directions, and the reply is where a leader learns it has been replaced. Suppose a leader from term 4 sends an append to a follower that has moved on to term 7. The follower refuses, and its refusal is stamped term 7. The old leader reads that number, adopts it, and steps down to being a follower before it can do any damage.

So one number does two jobs. On the way out it lets the receiver check whether the sender is current. On the way back it lets the sender find out that it is not. Nobody has to be told in words, and no machine has to keep a list of who has been leader.

Machine D is a follower in term 6. A message arrives stamped term 4, telling it to add an entry to its log. What should D do?
Refuse it, and stay in term 6. The message is real and the sender is a real machine that really was the leader once. It has been asleep, or cut off, and term 5 and term 6 happened without it. Obeying it would let stale instructions into an up-to-date log. Note the asymmetry: a term higher than your own is adopted immediately, and a term lower than your own is refused. Numbers only ever go up, which is what makes them safe to trust.
Step 3

Hold an election with a timeout, some votes and a majority

Nobody appoints the leader. There is no operator and no special machine, so the cluster has to pick one by itself out of a group of identical machines that can only send each other messages. Raft does it with a countdown and a vote.

Every follower runs a countdown called its election timeout. A message from the leader resets it. If the countdown reaches zero, the follower concludes that there is no leader worth waiting for. It adds one to its term, votes for itself, becomes a candidate, and asks every other machine for a vote. If it collects votes from more than half of the cluster, it is the leader. More than half is called a majority: in a cluster of five, a majority is three.

What is a tick, and where did the seconds go?

The cluster in these labs runs on ticks instead of seconds. A tick is one step of the simulation: first every message that is due gets delivered, then every machine's countdown goes down by one. A message takes a whole number of ticks to travel.

The point of ticks is that you can take one at a time and see the exact run that a fast animation would have blurred past. Nothing is waiting on a real clock, so nothing happens between your presses. In a real cluster a tick would be a few tens of milliseconds. The timeouts here of six to fourteen ticks would be a couple of hundred milliseconds of silence before somebody gets suspicious.

Lab 5 · An election, one tick at a time
Try this firstPress Tick once eight to twelve times. Watch the “fires in” number on each card count down. The first machine to reach zero becomes a candidate. Its vote request then needs one message trip out and each reply needs one trip back, so a leader cannot appear on the timeout tick itself. Messages appear under the cards, and the badges at the bottom report who leads and how many votes were needed.
Notice: the winner is whichever machine happened to time out first, and it will usually change when you press Start over; however, a random draw can pick the same winner twice. No machine is special and nothing is chosen in advance. Press Run to let it go by itself, and drag speed if it is too quick to follow.
Why more than half, rather than some other number?

Because two groups that are each more than half of the same cluster cannot exist. Any two majorities have to share at least one machine, and that shared machine only gives one vote per term. So if a majority elected somebody in term 9, no second machine can also collect a majority in term 9. One term, at most one leader, guaranteed by arithmetic rather than by hoping.

Lower the threshold and the guarantee is gone. In a cluster of five, two groups of two fit comfortably side by side with nothing shared, so both could crown a leader. The lab below does that sum for you and then really runs the cluster to check the sum was right.

Lab 6 · Choosing the threshold yourself
Try this firstWith 5 machines chosen, press 2 votes, then press Cut the cluster in two and run it. The table works out whether each side of the cut can reach two votes, and then five real machines run for 220 ticks with the two sides unable to reach each other. Afterwards press Use a real majority and run it again.
Notice: with a threshold of two you get two leaders, each certain it is in charge and unable to see the other. With three you get at most one, and the short side simply keeps trying forever without ever succeeding. Try 3 machines and 7 machines as well, and watch where the safe threshold lands each time.
What stops the countdowns once somebody is leading?

The leader keeps talking. Every few ticks it sends an append to every follower, and when there is nothing new to send it sends one anyway with no entries in it. That empty append is called a heartbeat, and its only job is to arrive. Receiving it resets the follower's countdown, so a follower that keeps hearing from a leader never times out.

You can watch this in Lab 5's row of messages, once somebody has won. An append that says "nothing new" is a heartbeat. It also means silence is the signal for everything: a follower does not need to be told the leader has died, and could not be, because a dead machine sends nothing. It only needs to notice that the heartbeats stopped.

You run four machines and let a machine call itself leader once it has two votes. The network then breaks into two pairs that cannot reach each other. What happens?
Each pair elects its own leader. Two votes is available to each pair on its own, and two groups of two share no machine, so no vote is being counted twice. There is no race to lose, which is what makes the third answer tempting and wrong: neither pair can see the other, so neither has anything to lose a race to. Both carry on happily, and the two logs go their own ways.
Step 4

A split vote, and the one line of randomness that breaks it

There is a hole in Step 3. Suppose every machine waits exactly the same number of ticks. Then they all give up at the same moment, all become candidates in the same term, and all vote for themselves. Five candidates with one vote each, and a majority is three, so nobody wins. That is a split vote.

The cluster is not stuck forever: the countdowns run again and another election starts. The trouble is that if the timeouts are still identical, the next election splits in exactly the same way, and so does the one after. The term number climbs and no work gets done. The fix is one line: each machine picks its own waiting time at random from a small range, so somebody gets there first.

What does random mean here, if the same run happens twice?

Random means unpredictable to the machines themselves, not unrepeatable. Each cluster in these labs is built from a starting number called a seed, and the same seed produces the same sequence of "random" waits every time. That is why Start over gives a different run: it moves to the next seed.

Repeatable randomness is how anybody debugs a system like this. A failure that only appears once is almost impossible to study. A failure you can reproduce by naming a number can be watched as many times as you need. Real clusters use a real random source, and the property that matters is the same in both cases: machines that were identical stop being identical.

Lab 7 · Make a split vote happen on purpose
Try this firstLeave the spread slider at 0 and press Run. Every machine waits exactly the same eight ticks, so the term badge climbs and the leader badge keeps saying "still no leader". Then drag the spread to 1 and press Run again: it stops the moment somebody wins.
Notice: one single tick of difference is enough. The randomness is not there to be large. It is there to stop the machines being identical, and being different by one tick is already not identical. Watch the vote messages at spread 0: every machine refuses everybody, because each has already voted for itself in that term.
Why can nobody win a split vote, even later in the same term?

Each machine has one vote per term and may not change its mind. A candidate votes for itself the moment it becomes one, so a five-way split leaves five machines all holding a spent vote. Nobody can reach three, however long everybody waits, because there are no unspent votes left in that term.

The way out is a new term. The countdowns keep running, somebody times out again, adds one to its term, and now every machine has a fresh vote to give in a term it has not voted in. So a split vote costs a term and a round trip of messages, and that is all it costs. Nothing is corrupted by one.

Lab 8 · How much randomness is enough
Try this firstPress Run 540 clusters. It builds sixty clusters at each of nine spread settings and runs every one until a leader appears or 120 ticks go by. Each bar is that measurement, not a figure from a table.
Notice: the first tick of spread does almost all of the work, and the eighth is no better than the second. Plot the outcome before increasing a tuning value. Here the useful range begins where split votes fall sharply and ends where more spread produces no measurable improvement.
Why does a candidate vote for itself, if that is what causes the deadlock?

Because the alternative is worse. Imagine a machine that held its vote back to see who else turned up. It would need a rule for how long to wait, and another for what to do if two candidates ask at once, and every such rule brings back the problem it was meant to solve. Voting for yourself needs no rule at all, and in a cluster of five it only costs you the election when at least three machines campaign at the same moment.

It also gives a small cluster something for nothing. A candidate in a three-machine cluster starts with one vote and needs only one more, so a single reply wins it. The split vote is the price, and Lab 8 measures the price as being close to nothing once the timeouts differ.

Every machine in a five-machine cluster waits exactly eight ticks before starting an election, and election after election ends with nobody elected. Which change fixes it?
Let each machine pick its own waiting time. Longer identical waits produce the same split vote, just less often, so the cluster spends longer with no leader and still ends up nowhere. Lowering the threshold to two does end the deadlock, and it also throws away the one thing that stops two leaders existing at once, which Step 3 measured. The cheap fix is to break the symmetry, and one tick of difference does it.
Step 5

The leader appends, and the followers agree

There is a leader now, so the cluster can do some work. A client is whatever program wants something done: a cash machine, a website, an app on a phone. It sends its command to the leader, and only to the leader. Followers turn clients away.

The leader writes the command at the end of its own log, onto its disk. That is the part of a machine that keeps what it was given even after the power goes off. Then it sends an append message to every follower. Writing it down is not the same as promising it happened. The leader may only tell the client "done" once a majority of machines hold that entry, and that is committing, which Step 7 pulls apart properly. Until then the entry is written but not promised.

What is actually inside an append message?

A message is a small bundle of named values, and each named value is a field. An append carries five of them. Three are straightforward: the leader's term, the new entries themselves, and how far the leader has committed. The other two describe the entry immediately before the new ones, and are called prevIndex and prevTerm.

Those last two are the interesting ones, and they are the subject of Step 6. They are not information the follower needs in order to write anything down. They are a claim about what the follower should already be holding and the follower checks the claim before it accepts a single entry.

Lab 9 · Send a command and follow it round
Try this firstPress Send the next command to the leader, then press Tick once three or four times. The entry appears on the leader's card first, then travels out as append messages, then appears on the followers. The badge counting how many of the five hold the top entry climbs as the replies come back.
Notice: the entry shows the term it was created in as a small number, then the command. A committed entry gets a check mark; an entry that is written but not yet promised does not. Send three or four commands and watch the check marks follow along a tick or two behind the entries themselves.
Why send an entry out before it is promised to anybody?

Because there is no other order available. An entry can only be promised once a majority hold it, and they can only hold it if somebody sent it to them. So every entry spends a short time in a state where it exists, is written on disk in several places, and is still not something the client has been told about.

That in-between state is where nearly every interesting failure in this course lives. Step 8 crashes the leader in the middle of it. If you find yourself asking "but what if it dies right now", you are asking the right question, and the answer is a whole step.

Lab 10 · One message, field by field
Try this firstPress the leader thinks C holds 2, read the table of fields, then press Deliver it. C accepts, because the claim matches what C really holds. Then press the leader thinks C holds 4 and deliver that one: same code, same follower, and a refusal.
Notice: the leader is guessing. It keeps a guess for every follower about how much of the log that follower already has. A fresh leader has no way to know, so it starts by assuming everybody is fully caught up. The guess is often wrong, and the whole of Step 6 is what happens when it is.
Why does the append carry several entries and not just the newest one?

Because a follower can be a long way behind, and one entry per message would take a long time to fix that. The leader sends everything from its guess for that follower onwards. A follower that missed ten entries can be handed all ten in one message, and is caught up after a single exchange.

This is also why the check in Step 6 is about the entry before the batch rather than about each entry in it. The batch is written or refused as one piece. A follower never ends up holding half of a message, which is one fewer state for anything to go wrong in.

The leader has taken a command from a client and written it as entry 6 of its own log. Nothing has been sent to anybody yet. May it tell the client the command is done?
Not until a majority hold it. Suppose the leader answered on the strength of its own copy alone. A crash one moment later would take the only copy with it, and a client would have been told about money that no surviving machine has heard of. Waiting for every machine sounds safer and is worse: one machine switched off for a week would stop the whole service. A majority is the balance point, and Step 8 shows exactly what it buys.
Step 6

What a follower does when its log does not match

A follower has been away. Its log is short, or it holds entries from an older leader that the rest of the cluster never agreed to. The new leader does not know which, because a leader keeps only a guess about each follower. Something has to find the disagreement and fix it, using nothing but messages.

The rule is short, and it is called the consistency check. Before writing anything, a follower checks the append's claim about the entry just before the new ones: index prevIndex should be from term prevTerm. If that does not match its own log, it refuses and writes nothing at all. The leader takes the refusal, lowers its guess by one entry, and tries again. Sooner or later the claim lands on an entry the two really do share, the follower accepts, and anything after that point on the follower is thrown away and replaced.

Why does checking one entry make the whole history safe?

Because the check was applied to every earlier entry too, so it reaches all the way back, one link at a time. A follower only ever accepted entry 40 after agreeing about entry 39, which it only accepted after agreeing about entry 38, and so on down to the empty log. So "we agree about entry 40" carries the whole of the history with it.

That is why one small comparison is enough, and why it has to be done before writing rather than afterwards. Accept an entry without the check and the chain is broken forever: from then on the two logs can differ anywhere below, and no later message would ever notice.

Lab 11 · Break a follower, then watch it get repaired
Try this firstPress Give C three entries from an older leader, then press One exchange four or five times. Each press runs the messages needed for one refusal or one acceptance, and the badges report the leader's guess next to what C really holds. Watch the guess walk down and then the log grow back.
Notice: the leader never asks C what it has, and C never explains. The only thing C ever says is yes or no. From a sequence of noes the leader works out where the two logs meet, which is the whole conversation. Press Take away three of C's entries and repair that too, then try Run until C matches.
I have not written code before: what is a function, and what is true or false?

A function is a named piece of code that takes some values in and hands one value back. In the lab below, accepts is handed three things and must hand back either true or false. Those two words are the only answers a yes-or-no question has in code, and a follower's decision is exactly a yes-or-no question.

One of the three values handed in is a list: several values in order under one name, which programmers usually call an array. myTerms is the list of terms of the entries the follower already holds, so myTerms[0] is entry 1's term and myTerms[1] is entry 2's term. The number in the brackets is the index, counted from zero, which is why entry 5 lives at myTerms[4]. That off-by-one is a real nuisance and everybody meets it.

Four more pieces of writing and you have everything the lab needs. return x means "hand back x and stop". if (test) { … } means "do the part in the curly brackets only when the test holds". === asks "are these two exactly equal", and it is three equals signs because one equals sign means something else. And myTerms.length is how many entries the list holds, so a claim about an index bigger than that is a claim about an entry the follower does not have.

Lab 12 · Write the rule yourself
Try this firstPress Run before changing anything. The starting rule says yes to everything, so it prints true twice when it should print true then false. Then fill in the rule and press Check against eleven hidden cases.
Notice: there are three cases and no more. A claim about index 0 is a claim about nothing, so it is always safe. A claim about an index past the end of your log cannot be true. Any other claim comes down to comparing one term with one term. If you get stuck, Show me one that works gives one answer, and changing it afterwards to see what breaks is where the understanding is.
Is backing up one entry at a time not painfully slow?

It can be. A follower that is a thousand entries out of step costs a thousand refusals, each one a round trip across the network, and Lab 11 lets you feel it at a small scale. The reason it is acceptable is that it is rare: this only happens after a leader change, and only for a follower that was away.

Real implementations speed it up without changing the idea. A refusing follower also reports the first index it holds from the term that clashed. That lets the leader skip a whole term's worth of guesses in one step instead of one entry at a time. The safety argument does not depend on the speed, so this is a speed-up rather than a different mechanism, and it is safe to leave out until the log gets long.

A follower holds three entries, from terms 3, 3 and 2. An append arrives claiming that entry 3 is from term 3. What happens?
It refuses, and the leader backs up one entry. Having an entry 3 is not the point. The follower's entry 3 came from term 2 and the leader claimed term 3. Those are two different entries that happen to sit at the same index, so everything from there on is suspect. Giving up would leave the follower broken forever. Backing up one at a time is slow in the worst case and always finds the meeting point, because the empty log matches everything.
Step 7

Decide when an entry is safe to act on

An entry in a log is a written note. A committed entry is a promise: the cluster will never lose it, never reorder it, and never put something else at that index, whatever crashes next. The rule is a count. When a majority of the machines hold the entry, the leader commits it, tells the client yes, and the balance may be reported as including it.

The leader keeps track of how much of the log each follower has, from the replies coming back, and looks for the highest index that a majority hold. Notice what it does not do. It does not take the largest number, and it does not trust any single machine, including itself.

What does committed actually promise, and to whom?

It promises the client that asked. Before an entry is committed, a client that asks "did my transfer happen" must be told no, or told nothing at all. After it is committed, the answer is yes, and no later event may turn that yes back into a no. Not a crash, not a network split, not an election.

That is why the count is a majority and why entries are on disk before they are counted. Any future majority must share at least one machine with this one, and that shared machine is holding the entry. So the entry cannot be lost by any group that is large enough to be allowed to decide anything.

Lab 13 · Drive the count by hand
Try this firstPress the + under machine C once. Now A, B and C all hold entry 1, the table row for entry 1 says three machines, and a check mark appears on entry 1 on each of those three cards. Keep pressing + under C and watch how far the promise reaches.
Notice: the committed line only moves when a third machine arrives, and it never moves because the leader wishes it would. Take that machine back down with and the committed entries stay committed: the table drops back to saying no, and the promise stands anyway, because a promise once made is not withdrawn. Start over empties the followers again, and from there five entries sit on A and B alone with nothing promised at all, because two machines are not a majority of five.
How do you count how many machines hold entry number n?

You walk the list and count. For a given n, look at each machine's total in turn. Add one to a running count every time that total is n or more. Then compare the count with the majority you need. That is what a loop in the code lab below does: repeat the same small piece of work once per machine.

To find the highest such n, do that for n equal to 1, then 2, then 3, and remember the largest one that reached a majority. It is not the fastest way and it is the clearest, and the whole list is at most a few dozen entries, so clearest wins.

The lab writes that out with four more pieces of code. let best = 0 gives a name to a value that is going to change; const need = … gives a name to one that will not. for (let n = 1; n <= 40; n = n + 1) is the loop: run the part in the curly brackets with n as 1, then as 2, and so on up to 40. for (const s of stored) is the same idea over a list: run it once for each machine's total, calling that total s. And s >= n asks "is s at least n", while Math.floor rounds a number down to a whole one, which is how you halve five and get two.

Lab 14 · Write the commit rule
Try this firstPress Run and read what the rule prints. It answers 0 and 0, because the two lines that do the counting are missing and nothing has been counted. The answers should be 5 and 3. Write those two lines, each marked FILL THIS IN, then press Check against twelve hidden clusters.
Notice: the hidden clusters include a cluster of one machine and clusters where nothing at all has reached a majority. Both are real situations, and a rule that only works on tidy inputs is a rule that loses somebody's money on an untidy day. Answer 0 when nothing is promised.
Does the leader count itself?

Yes, and it must. The leader is one of the five machines and it is holding the entry on its own disk, so it is one of the copies. In a cluster of five, a leader plus two followers is three machines, which is the majority, so two replies are enough. That is why the count in Lab 13 starts at one before any follower is added.

Counting itself is not the same as trusting itself. It contributes one, exactly like everybody else, and one is never a majority of five. The rule is doing arithmetic over the whole cluster and the leader has no special weight in it beyond being the machine that does the sum.

Five machines. The leader holds five entries, and the other four hold five, one, one and one. How far may the leader commit?
Up to entry 1. Count per entry rather than per machine. Entry 1 is on all five, so it clears the majority of three. Entry 2 is on two machines only, which is short, and so is everything above it. The machines do not disagree, by the way: the three short logs are correct as far as they go, and every entry they hold matches the leader's. They are behind, not wrong, and being behind is normal.
Step 8

A leader crashes in the middle of an append

Now the interesting part. A leader takes a command, writes it as entry 4, starts sending it out, and dies before the story finishes. Depending on the exact moment, the entry might be on nobody else, on one other machine, or on three. Only the last of those was ever promised to a client.

Whatever happened, the surviving machines notice the silence, hold an election and carry on. The question is what happens to entry 4. It has to survive if it was committed, and it is allowed to disappear if it was not, because in that case nobody was ever told anything about it.

What survives a crash, and why does the log come back?

A machine has two kinds of memory. Working memory is fast and forgets everything when the power goes. The disk is slower and keeps what it was given after a restart. Raft writes a log entry to disk before it answers for it, so a crashed machine comes back holding the same log and the same term it had when it fell over.

This is not a detail. The whole safety argument counts machines that hold an entry. A machine that forgets on restart would make the count meaningless, because an entry on three machines could be on zero after a power cut. The order matters too. Write first, answer second, because answering first and writing second is a promise that can evaporate.

Lab 15 · Crash the leader at a moment you choose
Try this firstLeave the slider at 0 and press Run it. The leader is crashed the instant after it takes the command, so entry 4 never leaves it and the badges report that it is gone from every machine that is up. Now drag the slider to 2 and press Run it again.
Notice: at some waits the entry vanishes, at some it survives without being committed, and at longer waits it was already committed and is kept. All three are correct. The one thing that never happens is an entry that was committed going missing, and the safety check reads all five logs after every run to confirm it. When Now send one more command lights up, press it.
Why can a new leader not just commit an old entry by counting it?

Because a count taken now can be undone by a machine that is currently switched off. An entry from an older term can sit on a majority of the machines that happen to be up. A machine that is down may be holding a longer log from that same period, and when it comes back it is entitled to replace that entry. Committing it would be a promise that a later election could break.

So Raft adds one condition to Step 7's rule: a leader only commits by counting when the entry was created in its own current term. Old entries come along for free. The moment a new leader gets one entry of its own onto a majority, everything below it is committed too, because a log is only ever accepted whole. That is what the second button in the lab above demonstrates.

One more rule earns its place here, and it is called the up-to-date rule. When machines vote, they do not vote for just anybody. A machine refuses a candidate whose log is behind its own. Behind means one of two things: the candidate's last entry is from an earlier term, or it is from the same term and the candidate's log is shorter. So a machine that missed the last few entries can never be elected over machines that have them.

Lab 16 · Which of these could win the next election
Try this firstClick could it win under the machines you think can win, then press Run the elections. Five elections are really run, one per machine, and each card's button then reads "can win" or "cannot win". Compare that with your picks.
Notice: B and C can win even though they are missing the top entry, because that entry sits on one machine and so was never committed. Losing it costs nobody a promise. D and E are two entries behind and can never gather three votes, however long they try. This is the rule that stops a stale machine erasing committed history.
Why does a machine that restarts come back as a follower?

Because it has no idea how long it was gone. A machine that woke up still calling itself leader would start sending appends stamped with an old term, into a cluster that may have held three elections while it was down. Coming back as a follower costs nothing. If there is a current leader it will hear from it within a few ticks, and if there is not, its countdown runs out and it can campaign like anybody else.

The term and the log come back from disk, so it is not starting from nothing. It keeps everything it knew and gives up only the claim to be in charge, which is the one thing it knew that could have gone stale while it was away.

A leader takes a command, gets it onto one other machine, and crashes. The client never got an answer. Is it acceptable for that entry to disappear?
Yes, and this is the deal the whole design rests on. The promise is about committed entries, and this one was on two machines out of five, which is short of a majority. The client is in the same position as somebody whose message never sent: no answer, so it retries. What would be unacceptable is an answer of yes followed by the entry vanishing. The third option is wrong for its reason: entries from crashed leaders are often kept, as the lab above shows.
Step 9

A split with two leaders, and why only one of them counts

Crashes are the easy failure, because a crashed machine stays quiet. The hard failure is a network that breaks in half while every machine keeps running. Each side sees the other side go silent and cannot tell whether those machines died or whether a wire came loose. This is called a split.

Cut five machines into a group of two and a group of three. The side of three hears nothing from the leader, times out, holds an election and elects somebody, because three is a majority. The old leader is over on the side of two, hears nothing to contradict it, and carries on calling itself leader. Two leaders at once, which sounds like the disaster this whole course exists to prevent.

What splits a network in half in real life?

Ordinary things. The box that wires one row of machines to the next stops working. Somebody sets a rule meant to keep strangers out, and it keeps their own machines out instead. A cable is unplugged while somebody is tidying. The long link between two buildings gets so busy that nearly everything sent along it is dropped. From inside a machine, all four look identical to the other machines having died.

That indistinguishability is the point, and it is why "just check whether the other one is alive" never works. No message can tell you the difference, because the whole problem is that messages are not arriving. Raft never tries to tell the two apart, which is why it survives both.

Lab 17 · Cut the cluster in two
Try this firstPress the side 1 button under the card marked leader, and under one other card. The button flips those two machines to side 2, and messages between the sides stop arriving. Then press Run and watch the three machines left on side 1 elect a leader of their own, while the old leader on side 2 carries on believing it is in charge.
Notice: the badge counting leaders can reach two, and the safety badge still says there are no problems. Both are true at once, and reconciling them is the point of this step. Try cutting the cluster into a one and a four, and then into two groups you choose, and watch which side can elect anybody. Join it back up puts it back.
Why does the stranded leader not notice it has lost?

Because nothing tells it. It sends appends into the silence and gets no replies, which is exactly what a busy or briefly congested network looks like. There is no message meaning "you were replaced", and there could not be one, since it would have to travel across the very link that is broken.

It finds out the moment the link comes back, and it finds out from one number. Any message it receives carrying a higher term makes it drop to being a follower at once. Until then it keeps trying, which is harmless, because trying is not the same as committing.

Lab 18 · Send a command to each of the two leaders
Try this firstPress the button that sends +50 to the small side, twice. The entries appear on that leader's log and stay without check marks forever. Then press the button that sends -30 to the big side and watch those entries commit within a tick or two.
Notice: being leader is not the privilege it sounds like. Calling yourself leader is free and commits nothing. The stranded leader can write in its own log all day and can never reach three machines, so it can never promise a client anything, and a client waiting on it simply waits. Only one of the two leaders can actually decide, and that is the one with the majority.
Why does the stranded side keep holding elections it cannot win?

Because it cannot tell that it is the stranded side. From inside those two machines, the picture is identical to three machines having burned down, and in that situation trying to elect somebody is exactly the right response. A rule like "stop trying after five failures" would leave a cluster leaderless after a genuine outage, which is worse than a machine wasting messages.

The cost of trying is small and bounded: a term number that climbs and a few messages that go nowhere. The moment the link comes back, those higher term numbers are actually useful, because they push the cluster into a fresh election that everybody can take part in.

The network cuts a five-machine cluster into a two and a three. The old leader is on the side of two and still calls itself leader. A client sends it a transfer. What does that client see?
It waits. The entry is written into that leader's log and never committed, so no answer is ever sent. The third option is what you would want, and the stranded leader cannot give it, because it has no way to know it lost. Waiting forever is unhelpful but it is not wrong: the client times out and retries somewhere else, and no lie was told. Real systems reduce the waiting by having a leader stand down when its followers go quiet, which is a refinement rather than a different idea.
Step 10

Rejoining, and watching the loser's log be overwritten

Nothing has been broken yet, but something is untidy. The stranded leader from Step 9 is holding entries that the rest of the cluster never agreed to, and the rest of the cluster has moved on with entries of its own. Both sides believe their own log. That is the state a real cluster is in the moment a broken link comes back.

Joining the network back up is enough to fix it, and the mechanism is one you already built. Step 6's consistency check finds the first index where the two logs disagree and the loser's entries from that point on are thrown away and replaced by the winner's.

Is throwing away entries not exactly the disaster we were avoiding?

It would be, if any of them had been committed. They were not. The stranded leader could only reach one other machine, so nothing it wrote ever sat on three of the five, so no client was ever told that any of it had happened. Discarding an entry nobody was promised costs nobody anything.

The rule from Step 8 is what makes this safe rather than lucky. A machine only wins an election if its log is at least as up to date as a majority of the cluster, so the winner already holds every committed entry there is. Anything it does not hold was, by that argument, never committed. The overwrite can only ever destroy notes, never promises.

Lab 19 · Join it back up and watch the ghost entries go
Try this firstPress Run 30 ticks before reconnecting anything. Nothing changes, because the two sides cannot talk. Now press Reconnect the network and then Run 30 ticks again.
Notice: the row underneath shows what the old leader held before, and each entry that has since been replaced is crossed out and marked. The old leader also stops calling itself leader, and it learns that from one number on one message: a term higher than its own. The safety check reports no problems throughout, which is the claim this whole course is built to support.
What a real cluster does that this one skips

Two things, and both are engineering rather than new ideas. A log that only grows would eventually fill any disk, so real implementations take a snapshot of the state now and then and throw away the entries that led up to it. A machine that is far behind is then sent the snapshot instead of ten million entries.

The other is changing the membership: adding a machine or removing one without ever having two different majorities that do not overlap. Raft handles it by moving through a combined configuration where a decision needs a majority of both the old and the new set. Neither changes anything you have built here, and both are safe to leave until you need them.

Lab 20 · Three machines, nothing to prove
Try this firstPress crash under any one card, then press Run. Two machines is still a majority of three, so the cluster keeps working. Then crash a second one and watch everything stop. Nothing here is marked.
Notice: a three-machine cluster survives exactly one failure, and it does not matter which machine it was. Restart a crashed machine and it comes back as a follower with the log it had, then catches up on its own. Try sending commands while one machine is down, and try cutting the network with the side buttons to see how little a group of one can do.
Which log wins, and who decides?

The leader's log wins, always, and nobody decides anything at the moment of the merge. There is no comparison of the two histories, no rule about which looks better, and no vote about it. A follower's only move is to say yes or no to a claim, and once it says yes, everything after that point is replaced by whatever the leader sends.

All the judgement happened earlier, at the election. Choosing a leader whose log is at least as up to date as a majority is what makes "the leader's log wins" a safe rule instead of a reckless one. Get the election right and the merge needs no cleverness at all, which is the part of Raft worth copying into other designs.

After the network is joined back up, two entries the stranded leader had written are thrown away. Whose money moved and then unmoved?
Nobody's. Those entries were notes, not promises. The client that sent them got no answer at all and will retry, which is the same position as a message that never arrived. The balance on that machine did change, and that is fine: a balance worked out from uncommitted entries was never something the cluster would report. The line between a note and a promise is the single most useful idea in this course.
Step 11

Run a five-machine cluster, and try to break it

Everything is built. You have elections with random timeouts and appends with a consistency check. You have repair by backing up one entry at a time, commit by counting a majority, and the up-to-date rule that decides who may be elected. Put them together and you have a cluster that can be attacked.

Below is the whole thing, with a safety check that really reads every log after every tick. It looks for two leaders in one term, two machines that have committed different commands at the same index, and two logs that disagree at an index where both claim the same term. There is a list of five things to try, and one of them is not achievable.

What the safety check actually reads

It walks every machine's log and compares it against every other machine's, entry by entry, at each index they both reach. It also keeps a record of what was committed at each index the first time anything committed there, and compares every later commit against that record. The panel reports how many comparisons it just did, so you can see it is doing work rather than displaying a reassuring word.

Checking history as well as the present matters. A cluster that committed +50 at index 4 and then quietly replaced it with -30 would look perfectly consistent at any single moment, because all five machines would agree on the wrong thing. Only a check that remembers can catch it.

Lab 21 · The whole cluster, and a check that keeps watch
Try this firstPress Run, then press Send a command three times, then press crash under the machine marked leader. The cluster goes quiet for a few ticks, elects somebody else and carries on. Then work down the list of five goals underneath.
Notice: the first three goals are all reachable, including two leaders at once. The last two are not, and they are really one goal twice over. The only way to make the check complain is to make a committed entry disappear, and that is the thing the rules forbid. Try hard: crash the leader mid-append, cut the network with the side buttons, send commands into the small side, bring everybody back at once. The check reads every log every tick and stays quiet, and that is the claim.
Why can I not make a committed entry disappear, however hard I try?

Because of two rules working together. A committed entry is on a majority of the machines. A machine can only be elected with votes from a majority, and no machine votes for a candidate whose log is behind its own. Any two majorities share at least one machine, and that machine is holding the entry, so it refuses anybody who does not have it.

So every leader that can ever exist already holds every committed entry, which means no leader can ever order that index overwritten. The argument uses no timing, no assumption about how fast messages travel, and no trust in any single machine. That is why it holds under any attack you can run in the panel above.

Lab 22 · The same attack, on a cluster with the rule wrong
Try this firstPress votes needed to win: 3 (a real majority) and then Run the attack. Read the safety panel. Then press votes needed to win: 2 (wrong) and run the identical attack again.
Notice: one number changed. Not the election code, not the repair code, not the commit rule. With a threshold of two, two machines have committed different commands at the same index, somebody was told their money moved when it did not, and the check names the exact index. The whole of the safety argument is carried by "more than half", and now you have seen what it is carrying.
What Raft does not promise

It does not promise the service keeps working. Crash three of the five machines in the panel above and the cluster stops accepting anything at all, correctly and on purpose, because no majority exists to promise with. Raft protects the truth of what it has already said, and it would rather stop than say something it might have to take back.

It does not promise speed either. Every command waits for a round trip to a majority, so a cluster spread across the world is slower than one in a single room, and no amount of tuning changes that. What you get in exchange is the one thing you cannot build afterwards: an answer of yes that stays true.

You cut the cluster into a two and a three, and both sides have a machine calling itself leader. Is the safety rule broken?
No, and this is the distinction worth taking away. The rule Raft guarantees is about committed entries, not about job titles. Two machines can believe they lead at once, and one of them is powerless, because promising anything needs three machines and it has two. The two leaders are never in the same term, by the way. The new one was elected in a higher term, and that number is how the old one finds out it lost the moment the link returns.

What you can do now

  • Explain why a group of machines keeps a log of commands rather than a stored answer.
  • Use a counter instead of a clock to put events from different machines in order.
  • Say why a leader needs more than half the votes, and what breaks at exactly half.
  • Break a deadlock between identical machines with one line of randomness.
  • Write the consistency check a follower applies before accepting an append.
  • Work out how far a leader may commit, by counting rather than by trusting.
  • Tell a written entry from a promised one, and know which one may be thrown away.
  • Attack a running cluster with crashes and splits, and say why the promises hold.

Where this goes

  • Real systems that run this. The rules you just built are the ones behind etcd, which keeps the configuration of a Kubernetes cluster, and behind Consul, TiKV and CockroachDB. When one of those elects a new leader in a few hundred milliseconds, this is what happened.
  • Inside a Database. A log that must survive a power cut, applied in order after a crash, is the write-ahead log of a database engine. The same idea one layer down, on one machine.
  • Build a Query Engine. Once several machines agree on the data, somebody has to answer questions about it quickly, which is a different kind of hard.
Step 12 · Advanced path

Persist before replying

A server's current term, its vote and new log entries are hard state. They must survive a restart. A voter that replies before its vote is durable can reboot and vote twice in one term. A follower that acknowledges an append before the entry is durable can make a leader count data that disappears in a power cut.

The integration boundary therefore has an order: write hard state, entries and any snapshot to durable storage; wait for the storage completion; only then send vote or append responses that depend on it. Committed entries are applied to the state machine in order. Applying before durability or exposing an uncommitted result breaks the promise.

Lab 23 · Crash between memory, disk and reply
Try this firstAcknowledge a vote in memory and crash before the disk write. Then enforce persist-before-reply and repeat for a log append.
Test every completion boundary: storage submit, durable completion, message send, commit advance and state-machine apply. The order is part of the protocol.
What “durable” means here

The storage layer must define when a completed write survives the failures in scope. A write accepted by an operating-system cache is not automatically safe from power loss.

A follower has copied an entry into memory. May it acknowledge that append?
The acknowledgement is evidence the leader may count.
Step 13

Do a client command once

A client can lose the leader's reply after its command commits. Retrying the same transfer as a new command would execute it twice. Give each client a stable session ID and each command an increasing request number. Replicate the latest number and result with the state-machine update, so every future leader can recognise a duplicate and return the saved result without applying the command again.

This produces one application effect for retries inside the retained session history. It does not make an email, card charge or other external side effect atomic with the Raft log. Those systems need their own stable idempotency key and durable effect record. Expiring a client session also expires part of the deduplication promise.

Lab 24 · Lose the reply and retry
Try this firstCommit request 7, drop its reply and retry it through a new leader. Compare a plain command with replicated session deduplication.
Include retries before commit, after commit, after leader change and after snapshot restore. The request number and saved result must move with replicated state.
Why the result is stored too

A duplicate request must receive the same logical answer without running again. Remembering only that a number was seen prevents duplication but cannot reproduce the response.

Where must the latest client request number be stored?
Deduplication state is part of the state machine.
Step 14

Serve a linearizable read

A machine can still think it is leader after losing contact with the majority. Reading its local state is fast but may be stale. One safe path puts a no-op in the new leader's term, confirms leadership with a quorum, obtains a read index and waits until the local state machine has applied through that index before answering.

A lease-based read can avoid the quorum exchange, but its safety depends on bounded clock drift and active quorum checking. A clock pause or backward step can extend a lease beyond reality. Label stale reads, quorum-confirmed reads and lease reads as different APIs rather than hiding the trade-off behind one “read” button.

Lab 25 · Read from an isolated old leader
Try this firstIsolate the old leader, commit a new value on the majority side and issue a local read. Then require quorum confirmation and applied-index catch-up.
Measure returned revision as well as value. A linearizable read needs evidence that leadership was current and the state machine had applied the safe index.
Why committing in the current term matters

A new leader first commits an entry from its own term before using the usual read-index reasoning. That establishes which prior entries are committed under Raft's current-term rule.

The current etcd Raft implementation documents quorum-confirmed and lease-based read paths.

An isolated old leader answers from local memory. What can it safely claim without more evidence?
Leadership is not a feeling. A current quorum must support the strong claim.
Step 15

Compact and install a snapshot

An ever-growing log is a recovery record, not a practical storage plan. After the application has applied through index k, it can save a snapshot of state plus the last included index and term. Only then may earlier log entries be discarded. The snapshot must also contain replicated client-session and membership state needed after recovery.

A follower behind the compacted prefix cannot be repaired with ordinary AppendEntries. The leader installs a snapshot, the follower verifies and persists it, restores the state machine, then continues with entries after the snapshot boundary. An interrupted transfer must not leave a half-snapshot presented as complete.

Lab 26 · Compact and catch up a slow follower
Try this firstApply through index 80, snapshot, compact, then reconnect a follower at index 20. Interrupt one snapshot transfer before installing it atomically.
Verify state hash, included index and term, membership, deduplication state and the first post-snapshot append. Storage savings alone are not a successful restore.
Snapshot versus backup

A Raft snapshot accelerates replica recovery and log compaction. It is not automatically an independent, historical or disaster-recovery backup; all replicas can faithfully agree on corrupted application state.

When may entries through index 80 be compacted?
The snapshot replaces the compacted prefix.
Step 16

Change membership safely

Changing five voters to a different five in one step can create two disjoint majorities, each able to decide. Joint consensus passes through a configuration where decisions require majorities of both the old and new voter sets. The overlap prevents two independent committed histories during the transition.

Add a new server as a non-voting learner first, let it catch up, then promote it through the configuration-change protocol. Remove failed members only while the current configuration can still commit the removal. A two-member cluster that loses one member cannot safely vote the missing member out; this is one reason production groups normally use at least three voters.

Lab 27 · Move from voters ABC to CDE
Try this firstSwitch directly and form two disjoint majorities. Then require old and new majorities in the joint phase before finalising CDE.
Test leader removal, learner lag, a crash during the joint phase and recovery from the last committed configuration. Configuration is replicated state, not an operator-side list.
Why one-at-a-time changes can also work

Some implementations preserve quorum overlap by allowing one voter change at a time and rejecting another while one is uncommitted. Follow the exact membership protocol your implementation proves, not a mixture of two designs.

The extended Raft paper derives joint consensus; etcd Raft documents its one-at-a-time implementation variant.

Why add a far-behind server as a learner first?
Promotion is a safety and availability event.
Step 17 · Current implementation practice

Reduce election disruption

A partitioned follower can repeatedly time out and increase its term. When it rejoins, its larger term makes a healthy leader step down even though the follower cannot win. Pre-vote asks peers whether an election would succeed before incrementing the term. The isolated node cannot collect enough pre-votes, so it does not disturb the cluster merely by returning.

Check-quorum makes a leader step down after it cannot confirm an active majority. Leadership transfer deliberately moves leadership to a caught-up target instead of waiting for competing timeouts. These are liveness and operational extensions; the core election and log safety rules still carry the proof.

Lab 28 · Rejoin a high-term follower
Try this firstIsolate one follower through five timeouts, reconnect it and count leader disruptions. Repeat with pre-vote, then transfer leadership to a caught-up follower.
Measure term changes, unavailable ticks and unsuccessful campaigns under loss and delay. An option that reduces disruption can still be misconfigured around timing.
Pre-vote does not elect a leader

It is a permission check for starting the real election. A successful pre-candidate still increments the term, requests actual votes and must win a majority under the normal rules.

What does pre-vote prevent an isolated node from doing repeatedly?
Ask before disrupting the term.
Step 18 · 2026 practice

Check the state machine

Protocol tests should generate sequences of messages, timeouts, storage completions, crashes, restarts, snapshots and membership changes. After every transition, check invariants: one vote per term, log matching, leader completeness, state-machine safety, monotonic commit and apply indexes, and no response before its required durable state.

Deterministic simulation makes a failing schedule replayable. Model checking explores small state spaces and can reduce a long failure to a short counterexample. Production traces add terms, indexes, message types, peer IDs, durable/applied positions and configuration IDs. AI can prioritise unusual schedules or summarise traces, but the executable model and invariant failure are the authority.

Lab 29 · Break one invariant and shrink the trace
Try this firstSelect persist-before-reply, current-term commit or quorum overlap. Disable it, run the generated schedule and remove events until only the minimal failure remains.
A passing simulation is not a proof of all executions. Record model bounds, explored states, random seeds, invariant definitions and the exact production behaviour outside the model.
What to observe in production

Track leader changes, proposal and commit latency, applied lag, fsync latency, snapshot size and duration, peer progress, rejected proposals, quorum loss and configuration changes. Alert on user impact and endangered safety assumptions, not term changes alone.

A simulator ran one million schedules without a violation. What has it proved?
State the bounds. Strong evidence is still bounded evidence.

Continue from consensus