Rust · deterministic simulation · no real network
Quorum is a from-scratch Raft consensus in Rust simulator. A candidate wins a majority, becomes leader, and replicates a log until most of the cluster holds it. Every timeout is seeded, every step is explicit, and the run below is the real state machine, not a canned animation.
runs the real election and replication state machine, client-side, no server, no CDN. Kill a node to force a re-election live.
Step advances the simulation one tick, delivering pending messages and firing any timers that are due. Play steps automatically until you pause. Each node card shows its role (follower, candidate, or leader), current term, and log.
Client request hands a new entry to the current leader so you can watch it replicate out to a majority and commit. Reset starts a fresh cluster. Try clicking a node to kill it once a leader is elected, then keep stepping to watch the survivors run a re-election. Same seed, same trace, every time.
Raft is famously easier to reason about than Paxos because it reduces to a small number of rules, enforced everywhere.
A node grants at most one vote per term, and only to a candidate whose log is at least as up to date as its own. That is what stops a stale node from ever winning.
A candidate becomes leader only once a strict majority of the cluster has voted for it in the same term. Ties and split votes just run again in a later term.
Any message carrying a higher term than a node has seen forces that node back to follower, immediately, even a sitting leader.
The leader only advances its commit index once a majority of nodes, itself included, have durably appended an entry from its own current term.
Most ways to learn Raft are either a real cluster you cannot pause or an animation that is not the real algorithm. Quorum is the deterministic middle.
Same seed and same sequence of calls, same trace, every time. A strange outcome is never a fluke you cannot get back, it is reproducible down to the tick.
A tiny seeded xorshift64* generator drives every election timeout, and messages ride an in-simulation bus with explicit delivery ticks. Nothing depends on the system clock or a socket.
Advance one tick at a time and watch pending messages deliver and timers fire. The browser demo and the CLI run the same state machine, not a canned recording.
The three roles, terms, votes, and the replicated log are typed throughout, and the library code does not panic. A run ends in a state you can inspect, not a crash.
What the simulation steps through
A node's election timer expires, it becomes a candidate, bumps its term, votes for itself, and asks every peer for a vote.
The winning leader appends client entries and sends AppendEntries to every follower, backing up next_index on a mismatch until logs line up.
Once match_index shows a majority holds an entry from the leader's current term, the leader advances commit_index and the entry is durable.
// src/sim.rs, the same logic this page runs in JavaScript
if votes_received.len() >= quorum_size() {
become_leader(candidate_id);
}
if count >= quorum && log[idx - 1].term == current_term {
commit_index = idx;
}
The same state machine, without a browser. Real output from the default seed.
$ cargo run -- run --nodes 5 --steps 2000
elected leader: node 3 (term 1, log length 3)
committed entries (3):
1: term 1 -> set x=1
2: term 1 -> set y=2
3: term 1 -> set z=3
cluster state:
node 0: follower term 1 log 3 commit 3 [up]
node 1: follower term 1 log 3 commit 3 [up]
node 2: follower term 1 log 3 commit 3 [up]
node 3: leader term 1 log 3 commit 3 [up]
node 4: follower term 1 log 3 commit 3 [up]
Run a whole cluster to convergence with quorum run --nodes 5 --steps 2000. The elected leader, committed log, per-node state, and event trace print out. --nodes, --steps, and --seed are all configurable.
cargo test runs the deterministic checks: exactly one leader is elected, an entry commits once a majority replicates it, a stale-log candidate cannot win, a higher term forces a step down, and a split vote resolves in a later term.
The node model, message bus, and seeded generator live in a plain Rust library, so the exact same simulation drives both the CLI and this in-browser port.