The Runtime Theory
SystemInternalsdistributed systems

Raft Leader Election: From Follower Timeout to the RequestVote Quorum

A step-by-step walk from a follower's election timeout to the RequestVote quorum that produces exactly one leader per term.

The Runtime Theory Team3 min read07 steps

layer stack

System

HWHardware
KKernel
RTRuntime
APPApplication
SYSSystem
CLIClient
NETNetwork
TLSCrypto
SRVServer

adjacent altitudes in this subsystem are still being traced

trace spine

  1. 01 election timer starts
  2. 02 follower times out
  3. 03 term bump and self-vote
  4. 04 RequestVote fanout
  5. 05 log freshness check
  6. 06 quorum reached
  7. 07 heartbeat stabilization

Every node in a Raft cluster starts as a follower: it does nothing but wait for heartbeats and reset a timer. That timer is the whole election. Here is the literal sequence, node by node.

trace stepSystem
When a node boots or first joins, it initializes currentTerm = 0 and arms an election timer with a duration sampled uniformly from 150–300ms (the classic randomization). The timer is monotonic — it runs even when the node is busy, because Raft uses the OS monotonic clock, not wall time.
trace stepSystem
A follower hears nothing — no heartbeats, no AppendEntries — for its full timeout. It concludes the leader is gone or unreachable and transitions to candidate. This is the only legal path to leader: nobody promotes you; you self-nominate.
trace stepSystem
The candidate increments currentTerm to term N and casts its own vote. The vote is recorded as votedFor = self. A node may grant at most one vote per term, and this one is already spent — which is why a node can never vote for two candidates in the same term.
trace stepSystem
The candidate sends a RequestVote RPC to every peer in parallel: term=N, candidateId, lastLogIndex, lastLogTerm. In etcd's implementation this is one goroutine per peer with a 1s RPC timeout, so the whole fanout completes in roughly one network RTT (~0.5–5ms in a datacenter).
trace stepSystem
Each peer votes only if (a) it has not voted this term and (b) the candidate's log is at least as fresh as its own: compare lastLogTerm first, then lastLogIndex. This guarantees the winner's log is the most complete — a candidate missing committed entries can never be elected. The vote reply carries the peer's term; if that term is higher than the candidate's, the candidate steps back down to follower immediately.
trace stepSystem
The candidate counts grant votes. In a 5-node cluster the bar is 3; in 3 nodes, 2. No two candidates can both reach N/2+1 in the same term — the majority is mathematically exclusive. If the term ends with no majority (a split vote), every node times out again and the whole cycle restarts at term N+1. Randomization is what makes the next attempt collide less.
trace stepSystem
The winner's first act is to broadcast empty AppendEntries (heartbeats) to every follower immediately, then every 100ms (etcd default). Each heartbeat resets the followers' election timers. Election machinery freezes until the leader fails again — that's the steady state.

A realistic term in pseudocode:

text
on election_timeout:
    currentTerm += 1
    votedFor = self
    votes = 1
    send RequestVote(term=currentTerm, lastLogIndex, lastLogTerm) to all peers
    wait up to 1 RTT
    if votes >= majority: become leader, broadcast heartbeats
    else: back to follower, re-arm randomized timer

The cost story: a failover takes roughly one randomized timeout (150–300ms) plus one RTT for the vote round — sub-second in etcd's default 1s heartbeat / 2s timeout tuning. During that window the cluster is read-only: writes are rejected with ErrLeaderChanged-style errors because no leader's log is authoritative until the quorum exists.

The tradeoff that defines the design is between speed and safety: wide random timeouts make split elections rare but slow failover; strict log-freshness makes elections safe but occasionally blocks a well-connected candidate whose log is behind. That tradeoff, plus the one-vote-per-term rule, is what makes "at most one leader per term" a theorem instead of a hope.