<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shinde Aditya</title>
    <description>The latest articles on DEV Community by Shinde Aditya (@heyshinde).</description>
    <link>https://dev.to/heyshinde</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1123188%2Fc7634bac-db7d-44de-8be2-29f5319d57ae.jpg</url>
      <title>DEV Community: Shinde Aditya</title>
      <link>https://dev.to/heyshinde</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/heyshinde"/>
    <language>en</language>
    <item>
      <title>Distributed Consensus: Raft vs Multi-Paxos &amp; State Machine Replication</title>
      <dc:creator>Shinde Aditya</dc:creator>
      <pubDate>Wed, 09 Sep 2026 14:44:02 +0000</pubDate>
      <link>https://dev.to/heyshinde/distributed-consensus-raft-vs-multi-paxos-state-machine-replication-4odd</link>
      <guid>https://dev.to/heyshinde/distributed-consensus-raft-vs-multi-paxos-state-machine-replication-4odd</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This deep dive was originally published on &lt;a href="https://www.initnode.dev/signal/raft-consensus-multi-paxos-state-machine-replication" rel="noopener noreferrer"&gt;InitNode Signal&lt;/a&gt;. Explore the interactive systems curriculum on &lt;a href="https://www.initnode.dev/graph" rel="noopener noreferrer"&gt;InitNode Graph&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Architectural Abstract&lt;/strong&gt;: Building distributed systems that survive arbitrary network partitions, hardware degradation, and node crashes requires consensus—the algorithmic agreement across independent compute nodes on a linear sequence of state transitions. While Leslie Lamport's &lt;strong&gt;Paxos&lt;/strong&gt; established the theoretical baseline, Diego Ongaro and John Ousterhout's &lt;strong&gt;Raft&lt;/strong&gt; transformed distributed engineering by decomposing consensus into discrete, comprehensible sub-problems. This blueprint deconstructs the mathematical invariants, state machine transitions, log compaction mechanics, and failure modes of &lt;strong&gt;Multi-Paxos&lt;/strong&gt; and &lt;strong&gt;Raft&lt;/strong&gt;, examining how production engines like &lt;code&gt;etcd&lt;/code&gt;, &lt;code&gt;CockroachDB&lt;/code&gt;, &lt;code&gt;TiKV&lt;/code&gt;, and &lt;code&gt;Kafka KRaft&lt;/code&gt; achieve linearizable guarantees under chaotic network conditions.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. The Core Dilemma: Replicated State Machines &amp;amp; FLP Impossibility
&lt;/h2&gt;

&lt;p&gt;At the heart of distributed coordination, distributed databases, and consensus metadata quorums lies the &lt;strong&gt;Replicated State Machine (RSM)&lt;/strong&gt; architecture.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    subgraph ClientLayer["Client Layer"]
        C1["Client 1"]
        C2["Client 2"]
    end

    subgraph NodeA["Node A (Leader)"]
        SM_A["Deterministic State Machine"]
        Log_A["Replicated Append-Only Log"]
        Cons_A["Consensus Module"]
    end

    subgraph NodeB["Node B (Follower)"]
        SM_B["Deterministic State Machine"]
        Log_B["Replicated Append-Only Log"]
        Cons_B["Consensus Module"]
    end

    subgraph NodeC["Node C (Follower)"]
        SM_C["Deterministic State Machine"]
        Log_C["Replicated Append-Only Log"]
        Cons_C["Consensus Module"]
    end

    C1 --&amp;gt;|Command Proposal| Cons_A
    C2 --&amp;gt;|Command Proposal| Cons_A

    Cons_A &amp;lt;--&amp;gt;|Consensus Protocol RPC| Cons_B
    Cons_A &amp;lt;--&amp;gt;|Consensus Protocol RPC| Cons_C

    Cons_A --&amp;gt;|Append| Log_A
    Cons_B --&amp;gt;|Append| Log_B
    Cons_C --&amp;gt;|Append| Log_C

    Log_A --&amp;gt;|Committed Entries| SM_A
    Log_B --&amp;gt;|Committed Entries| SM_B
    Log_C --&amp;gt;|Committed Entries| SM_C&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  The State Machine Property
&lt;/h3&gt;

&lt;p&gt;If two identical, deterministic state machines start in the same initial state $S_0$ and apply the exact same sequence of input commands:&lt;/p&gt;

&lt;p&gt;$$C = [e_1, e_2, e_3, \dots, e_k]$$&lt;/p&gt;

&lt;p&gt;they are mathematically guaranteed to traverse the identical sequence of intermediate states and arrive at the exact same final state $S_k$:&lt;/p&gt;

&lt;p&gt;$$S_k = f(S_{k-1}, e_k) = f(f(\dots f(S_0, e_1), \dots), e_k)$$&lt;/p&gt;

&lt;p&gt;Consensus is therefore reduced to an agreement problem: &lt;strong&gt;ensuring that all non-faulty nodes commit and execute identical log commands in the identical sequence.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  The FLP Impossibility Result (Fischer, Lynch, Paterson — 1985)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The FLP Impossibility Theorem&lt;/strong&gt;: In an asynchronous distributed network, no deterministic consensus protocol can guarantee both Safety and Liveness in the presence of even a single unannounced crash failure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safety ("Nothing Bad Happens")&lt;/strong&gt;: All non-faulty nodes agree on the same value, and the agreed value must have been proposed by a client (no phantom states or split-brain divergences).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liveness ("Something Good Eventually Happens")&lt;/strong&gt;: Every non-faulty node eventually decides upon a value without halting or deadlocking indefinitely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because real-world networks (like AWS VPCs, cross-region fiber, and Kubernetes overlays) are &lt;strong&gt;asynchronous&lt;/strong&gt;—meaning message delivery delays and processing times are unbounded—practical consensus algorithms (&lt;strong&gt;Multi-Paxos&lt;/strong&gt;, &lt;strong&gt;Raft&lt;/strong&gt;, &lt;strong&gt;Zab&lt;/strong&gt;) prioritize &lt;strong&gt;Safety over Liveness&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;They guarantee that under any arbitrary network partition or delay, the cluster will &lt;strong&gt;never violate linearizability&lt;/strong&gt;. To regain liveness, they rely on &lt;strong&gt;partial synchrony&lt;/strong&gt; (e.g., randomized election timers or heartbeat timeouts where communication delays are temporarily bounded).&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Multi-Paxos: Theory, Ballots &amp;amp; Hole-Filling
&lt;/h2&gt;

&lt;p&gt;Leslie Lamport’s original &lt;strong&gt;Classic Paxos&lt;/strong&gt; (Single-Decree Paxos) reaches agreement on only a &lt;strong&gt;single log slot&lt;/strong&gt; across a collection of three distinct roles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Proposers&lt;/strong&gt;: Nodes that advocate client values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acceptors&lt;/strong&gt;: The consensus memory quorum that stores and votes on proposed values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learners&lt;/strong&gt;: Nodes that execute the decided value once a quorum is achieved.
&lt;/li&gt;
&lt;/ol&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    actor Proposer as Proposer (Node A)
    participant Acceptors as Acceptor Quorum (N/2 + 1)
    actor Learners as Learners / State Machine

    Note over Proposer, Acceptors: Phase 1: Prepare &amp;amp; Promise (Ballot Acquisition)
    Proposer-&amp;gt;&amp;gt;Acceptors: Prepare(ballot_n)
    Acceptors--&amp;gt;&amp;gt;Proposer: Promise(ballot_n, max_accepted_val, max_accepted_ballot)

    Note over Proposer, Acceptors: Phase 2: Accept &amp;amp; Accepted (Value Commitment)
    Proposer-&amp;gt;&amp;gt;Acceptors: Accept(ballot_n, proposed_val)
    Acceptors--&amp;gt;&amp;gt;Proposer: Accepted(ballot_n, proposed_val)
    Acceptors--&amp;gt;&amp;gt;Learners: Commit Decided Value&lt;/code&gt;&lt;/pre&gt;






&lt;h3&gt;
  
  
  Classic Paxos: The 2-Phase Round Trip
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Phase 1a: Prepare
&lt;/h4&gt;

&lt;p&gt;A Proposer chooses a unique, monotonically increasing proposal number $n$ (where $n = \text{round} \cdot \text{total_nodes} + \text{node_id}$) and broadcasts &lt;code&gt;Prepare(n)&lt;/code&gt; to a majority of Acceptors.&lt;/p&gt;

&lt;h4&gt;
  
  
  Phase 1b: Promise
&lt;/h4&gt;

&lt;p&gt;When an Acceptor receives &lt;code&gt;Prepare(n)&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If $n &amp;gt; \text{highest_promised_ballot}$, the Acceptor promises never to accept any future proposals numbered less than $n$, and returns:
$$\text{Promise}(n, v_{\text{max}}, n_{\text{max}})$$
where $v_{\text{max}}$ is the highest-numbered proposal value it has already accepted (if any), and $n_{\text{max}}$ is the ballot number at which it accepted $v_{\text{max}}$.&lt;/li&gt;
&lt;li&gt;If $n \le \text{highest_promised_ballot}$, the message is rejected or ignored.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Phase 2a: Accept
&lt;/h4&gt;

&lt;p&gt;Once the Proposer receives promises from a majority ($\lfloor N/2 \rfloor + 1$) of Acceptors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It selects value $v$:

&lt;ul&gt;
&lt;li&gt;If any Acceptor returned a previously accepted value in Phase 1b, $v$ &lt;strong&gt;must&lt;/strong&gt; be set to the value associated with the highest $n_{\text{max}}$ among all promises.&lt;/li&gt;
&lt;li&gt;If no Acceptor had previously accepted a value, the Proposer is free to use its own client-provided value $v_{\text{client}}$.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The Proposer broadcasts &lt;code&gt;Accept(n, v)&lt;/code&gt; to the Acceptors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Phase 2b: Accepted
&lt;/h4&gt;

&lt;p&gt;When an Acceptor receives &lt;code&gt;Accept(n, v)&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It accepts $(n, v)$ if and only if it has not promised to ignore ballot $n$ (i.e., $\text{highest_promised_ballot} \le n$).&lt;/li&gt;
&lt;li&gt;It broadcasts &lt;code&gt;Accepted(n, v)&lt;/code&gt; to the Proposer and Learners.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Multi-Paxos: Eliminating Phase 1 Overheads
&lt;/h3&gt;

&lt;p&gt;Classic Paxos requires &lt;strong&gt;2 full round-trip times (RTTs)&lt;/strong&gt; for &lt;em&gt;every single log entry&lt;/em&gt;. In a high-throughput database, running Phase 1 for every write is catastrophic for latency.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Invariant&lt;/strong&gt;: Phase 1 is executed only once per leadership epoch. For all subsequent log commands, Phase 1 is skipped entirely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For all subsequent log entries, the Leader skips directly to &lt;strong&gt;Phase 2 (Accept $\to$ Accepted)&lt;/strong&gt;, reducing steady-state commit latency to &lt;strong&gt;1 RTT&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    actor Client
    participant Leader as Stable Multi-Paxos Leader
    participant Acceptors as Acceptors Quorum

    Note over Leader,Acceptors: Stable Leadership Established (Phase 1 pre-executed)
    Client-&amp;gt;&amp;gt;Leader: WriteCommand(X = 10)
    Leader-&amp;gt;&amp;gt;Acceptors: Accept(slot_101, ballot_5, X=10)
    Acceptors--&amp;gt;&amp;gt;Leader: Accepted(slot_101, ballot_5)
    Note over Leader: Quorum Achieved (1 RTT)
    Leader--&amp;gt;&amp;gt;Client: Success (Committed in Slot 101)&lt;/code&gt;&lt;/pre&gt;






&lt;h3&gt;
  
  
  The Complexities of Multi-Paxos in Production
&lt;/h3&gt;

&lt;p&gt;While Multi-Paxos looks clean in academic papers, production implementations (such as Google’s &lt;strong&gt;Chubby&lt;/strong&gt; and &lt;strong&gt;Spanner&lt;/strong&gt;) encountered severe real-world engineering hurdles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Log Gaps ("Holes")&lt;/strong&gt;: In Multi-Paxos, slots can be decided out of order. If Slot 101 and Slot 103 are committed, but Slot 102 suffers packet loss, the State Machine cannot advance past Slot 100. The Leader must execute a &lt;code&gt;no-op&lt;/code&gt; proposal in Slot 102 to fill the hole before proceeding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leader Changes with Uncommitted Slots&lt;/strong&gt;: When a new Leader takes over, it must run Phase 1 across an unbounded range of uncommitted slots to discover any partially accepted proposals from the previous Leader.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role Confusion &amp;amp; Quorum Invariants&lt;/strong&gt;: Because Proposers, Acceptors, and Learners can be decoupled or co-located in arbitrary topologies, formal verification of dynamic cluster membership changes becomes intensely difficult.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. Raft Deconstructed: Consensus Through Understandability
&lt;/h2&gt;

&lt;p&gt;Designed by Diego Ongaro and John Ousterhout at Stanford in 2014, &lt;strong&gt;Raft&lt;/strong&gt; was engineered with a primary design objective: &lt;strong&gt;Understandability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Raft achieves the exact same formal safety guarantees as Multi-Paxos but decomposes the consensus problem into three strictly defined, independent sub-problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Leader Election&lt;/strong&gt;: Selecting a single cluster leader upon startup or heartbeat failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log Replication&lt;/strong&gt;: Unidirectional distribution and reconciliation of log entries from the Leader to Followers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety&lt;/strong&gt;: Enforcing invariants that prevent state machine divergence across leadership transitions.
&lt;/li&gt;
&lt;/ol&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;stateDiagram-v2
    [*] --&amp;gt; Follower

    Follower --&amp;gt; Candidate: Election Timeout Fires (No Heartbeat)
    Candidate --&amp;gt; Candidate: Split Vote / Timeout (Increment Term, New Ballot)
    Candidate --&amp;gt; Leader: Receives Votes from Majority Quorum
    Candidate --&amp;gt; Follower: Discovers New Leader or Higher Term
    Leader --&amp;gt; Follower: Discovers Peer with Higher Term&lt;/code&gt;&lt;/pre&gt;






&lt;h3&gt;
  
  
  The Raft Cluster Node Invariant Matrix
&lt;/h3&gt;

&lt;p&gt;At any point in logical time, each node in a Raft cluster exists in one of three mutually exclusive roles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Operational Invariant &amp;amp; Responsibilities&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;Follower&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Passive. Responds to incoming &lt;code&gt;RequestVote&lt;/code&gt; and &lt;code&gt;AppendEntries&lt;/code&gt; RPCs from Candidates and Leaders. Never initiates RPCs. If no communication is received within a randomized election timeout, transitions to &lt;code&gt;Candidate&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;Candidate&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Active Campaigner. Increments logical &lt;code&gt;currentTerm&lt;/code&gt;, votes for itself, and broadcasts &lt;code&gt;RequestVote&lt;/code&gt; RPCs to all peers. Strives to collect $\lfloor N/2 \rfloor + 1$ affirmative votes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;Leader&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Authoritative Master. Handles all client proposals, dictates log appending, coordinates commit indices, and broadcasts periodic &lt;code&gt;AppendEntries&lt;/code&gt; heartbeats (every $50\text{ms}$) to suppress follower elections.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  1. Randomized Election Timers &amp;amp; Split-Vote Prevention
&lt;/h3&gt;

&lt;p&gt;In symmetric protocols, when a Leader crashes, multiple followers simultaneously time out and become candidates. If Node B and Node C both request votes at Term 2 in a 4-node cluster, each might collect 2 votes, causing a &lt;strong&gt;Split Vote&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;$$\text{Votes}(\text{Node B}) = 2, \quad \text{Votes}(\text{Node C}) = 2 \quad (\text{Threshold } \ge 3)$$&lt;/p&gt;

&lt;p&gt;Neither candidate achieves a majority, the election times out, and the cluster risks perpetual livelock.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant NodeA as Node A (Timeout: 170ms)
    participant NodeB as Node B (Timeout: 290ms)
    participant NodeC as Node C (Timeout: 240ms)

    Note over NodeA: 170ms timer fires first!
    NodeA-&amp;gt;&amp;gt;NodeA: Become Candidate, Term = 2, Vote for Self
    NodeA-&amp;gt;&amp;gt;NodeB: RequestVote(Term=2, CandidateId=A, LastLogIdx=10, LastLogTerm=1)
    NodeA-&amp;gt;&amp;gt;NodeC: RequestVote(Term=2, CandidateId=A, LastLogIdx=10, LastLogTerm=1)
    NodeB--&amp;gt;&amp;gt;NodeA: VoteGranted(Term=2)
    NodeC--&amp;gt;&amp;gt;NodeA: VoteGranted(Term=2)
    Note over NodeA: Majority (3/3) Reached!
    NodeA-&amp;gt;&amp;gt;NodeA: Become Leader
    NodeA-&amp;gt;&amp;gt;NodeB: AppendEntries Heartbeat(Term=2)
    NodeA-&amp;gt;&amp;gt;NodeC: AppendEntries Heartbeat(Term=2)
    Note over NodeB,NodeC: Timers reset to 0&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Raft eliminates split-vote livelocks using &lt;strong&gt;randomized election timeouts&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;$$T_{\text{election}} \in [T_{\text{min}}, T_{\text{max}}] \quad (\text{typically } [150\text{ms}, 300\text{ms}])$$&lt;/p&gt;

&lt;p&gt;Because timeout intervals are chosen randomly from a uniform distribution, one node’s timer almost always fires significantly ahead of its peers (e.g., $170\text{ms}$ vs $240\text{ms}$). The winning candidate claims the majority votes and broadcasts heartbeats before competitors time out, ensuring elections resolve in a single round trip.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Log Replication &amp;amp; The Strong Leader Invariant
&lt;/h3&gt;

&lt;p&gt;In Raft, logs flow strictly in &lt;strong&gt;one direction&lt;/strong&gt;: from the &lt;strong&gt;Leader to Followers&lt;/strong&gt;. Followers never overwrite or modify the Leader’s log entries.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    subgraph LeaderLog["Leader Log (Term 2)"]
        L1["[1] Term:1 (Set X=5)"]
        L2["[2] Term:1 (Set Y=2)"]
        L3["[3] Term:2 (Set Z=9) - COMMITTED"]
        L4["[4] Term:2 (Set X=8) - UNCOMMITTED"]
    end

    subgraph Follower1Log["Follower 1 Log"]
        F1_1["[1] Term:1 (Set X=5)"]
        F1_2["[2] Term:1 (Set Y=2)"]
        F1_3["[3] Term:2 (Set Z=9)"]
    end

    subgraph Follower2Log["Follower 2 Log (Lagging / Inconsistent)"]
        F2_1["[1] Term:1 (Set X=5)"]
        F2_2["[2] Term:1 (Set Y=2)"]
        F2_3["[3] Term:1 (Set Z=1) ⚠️ MISMATCH"]
    end

    L3 --&amp;gt;|Replicated to Majority| F1_3
    L4 -.-&amp;gt;|In Flight| F1_1
    L3 --&amp;gt;|Leader forces match: Overwrite Slot 3| F2_3&lt;/code&gt;&lt;/pre&gt;



&lt;h4&gt;
  
  
  The Log Matching Property
&lt;/h4&gt;

&lt;p&gt;Raft enforces two critical invariants:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If two entries in different logs have the same index and term, they store the exact same command.&lt;/li&gt;
&lt;li&gt;If two entries in different logs have the same index and term, then their logs are &lt;strong&gt;identical in all preceding entries&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  AppendEntries Consistency Check
&lt;/h4&gt;

&lt;p&gt;When the Leader sends &lt;code&gt;AppendEntries(term, leaderId, prevLogIndex, prevLogTerm, entries[], leaderCommit)&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The follower checks its local log at &lt;code&gt;prevLogIndex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the follower does not have an entry at &lt;code&gt;prevLogIndex&lt;/code&gt; with term &lt;code&gt;prevLogTerm&lt;/code&gt;, it &lt;strong&gt;rejects&lt;/strong&gt; the request (&lt;code&gt;Success = false&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Upon rejection, the Leader decrements &lt;code&gt;nextIndex&lt;/code&gt; for that follower and retries until a common ancestor is reached. Once the follower accepts, it overwrites any conflicting uncommitted entries with the Leader’s authoritative entries.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Log Compaction &amp;amp; Memory-Mapped Snapshots
&lt;/h3&gt;

&lt;p&gt;An append-only log cannot grow indefinitely in memory. As transactions accumulate, disk and RAM exhaustion will crash the process.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    subgraph InactiveLog["Compacted into Snapshot"]
        S1["Entry 1: Set a=1"]
        S2["Entry 2: Set b=2"]
        S3["Entry 3: Set a=5"]
        S4["Entry 4: Set c=8"]
    end

    subgraph Snapshot["Raft Snapshot File"]
        State["State Machine State:\n{a: 5, b: 2, c: 8}\nLast Included Index: 4\nLast Included Term: 2"]
    end

    subgraph ActiveLog["Active In-Memory Log"]
        L5["Entry 5: Term 2 (Set d=12)"]
        L6["Entry 6: Term 3 (Set a=9)"]
    end

    InactiveLog --&amp;gt;|Point-in-Time Discard| Snapshot
    Snapshot -.-&amp;gt;|Persisted to Disk| ActiveLog&lt;/code&gt;&lt;/pre&gt;



&lt;h4&gt;
  
  
  Snapshot Structure
&lt;/h4&gt;

&lt;p&gt;When the log reaches a predefined byte limit (e.g., &lt;code&gt;64MB&lt;/code&gt; in &lt;code&gt;etcd&lt;/code&gt;), the state machine creates a point-in-time snapshot containing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Applied State Data&lt;/strong&gt;: The complete key-value or relational dataset state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;lastIncludedIndex&lt;/code&gt;&lt;/strong&gt;: The highest log index applied to the snapshot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;lastIncludedTerm&lt;/code&gt;&lt;/strong&gt;: The term of &lt;code&gt;lastIncludedIndex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cluster Configuration&lt;/strong&gt;: The active membership schema at &lt;code&gt;lastIncludedIndex&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the snapshot is flushed to disk, all log entries through &lt;code&gt;lastIncludedIndex&lt;/code&gt; are discarded. If a lagging follower is so far behind that its &lt;code&gt;nextIndex&lt;/code&gt; is no longer in the Leader’s log, the Leader streams the snapshot via the &lt;code&gt;InstallSnapshot&lt;/code&gt; RPC.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Cluster Membership Changes: Joint Consensus
&lt;/h3&gt;

&lt;p&gt;Changing cluster membership dynamically (e.g., adding Node D and Node E to an existing 3-node cluster) is hazardous. If nodes switch their configuration independently, the cluster can temporarily have &lt;strong&gt;two disjoint majorities&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    subgraph DisjointMajorities["Split Quorum Risk during Naive Reconfiguration"]
        OldQuorum["Old Config (Nodes 1, 2, 3)\nMajority = 2\n(Nodes 1, 2 elect Node 1)"]
        NewQuorum["New Config (Nodes 1, 2, 3, 4, 5)\nMajority = 3\n(Nodes 3, 4, 5 elect Node 5)"]
    end

    OldQuorum ---|Simultaneous Existence| NewQuorum&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;To prevent split-brain during configuration transitions, Raft uses a two-phase &lt;strong&gt;Joint Consensus&lt;/strong&gt; approach:&lt;/p&gt;

&lt;p&gt;$$C_{\text{old}} \longrightarrow C_{\text{old,new}} \longrightarrow C_{\text{new}}$$&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant Leader
    participant QuorumOld as Old Majority (C_old)
    participant QuorumNew as New Majority (C_new)

    Note over Leader: Step 1: Propose Joint Config C_old,new
    Leader-&amp;gt;&amp;gt;QuorumOld: AppendEntries(C_old,new)
    Leader-&amp;gt;&amp;gt;QuorumNew: AppendEntries(C_old,new)
    Note over Leader: Requires separate majorities from BOTH C_old AND C_new

    Note over Leader: Step 2: Commit C_old,new &amp;amp; Propose C_new
    Leader-&amp;gt;&amp;gt;QuorumOld: AppendEntries(C_new)
    Leader-&amp;gt;&amp;gt;QuorumNew: AppendEntries(C_new)
    Note over Leader: Fully transitioned to C_new!&lt;/code&gt;&lt;/pre&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enter Joint Consensus ($C_{\text{old,new}}$)&lt;/strong&gt;: The Leader logs and commits a configuration entry containing both $C_{\text{old}}$ and $C_{\text{new}}$. Decisions (elections and log commits) require &lt;strong&gt;separate majorities from both the old configuration and the new configuration independently&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finalize ($C_{\text{new}}$)&lt;/strong&gt;: Once $C_{\text{old,new}}$ is committed, the Leader creates an entry for $C_{\text{new}}$ and replicates it. Once $C_{\text{new}}$ is committed, nodes not in $C_{\text{new}}$ are gracefully shut down.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  4. Multi-Paxos vs. Raft: Complete Architectural Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Architectural Vector&lt;/th&gt;
&lt;th&gt;Multi-Paxos (Chubby, Spanner)&lt;/th&gt;
&lt;th&gt;Raft (etcd, CockroachDB, TiKV, KRaft)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Design Philosophy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Symmetric mathematical abstraction; consensus separated from state machine.&lt;/td&gt;
&lt;td&gt;Understandability, symmetric role decomposition, strong leader hierarchy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Leader Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Weak / Emergent leader. Multiple proposers can propose values simultaneously; leader is an optimization to skip Phase 1.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Strong Leader&lt;/strong&gt;. All proposals, log replication, and commit decisions flow strictly through the leader.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Log Gaps ("Holes")&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Allowed&lt;/strong&gt;. Slots can be committed out of order ($S_1, S_3$ committed while $S_2$ pending). Requires &lt;code&gt;no-op&lt;/code&gt; filling.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Forbidden&lt;/strong&gt;. Logs are strictly contiguous. Entry $k$ cannot be committed unless entries $1 \dots k-1$ are committed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Leader Election Mechanism&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;External lease manager, Paxos ballot voting, or Chubby master lock.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Randomized Election Timers&lt;/strong&gt; ($150\text{ms} - 300\text{ms}$) with built-in term progression.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Read Linearizability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Master leases with physical clock synchronization (TrueTime in Spanner).&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;ReadIndex Protocol&lt;/strong&gt; / &lt;strong&gt;Leader Leases&lt;/strong&gt; with quorum heartbeat confirmation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dynamic Membership&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complex epoch-based reconfiguration protocols; prone to race conditions without formal proofs.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Joint Consensus&lt;/strong&gt; ($C_{\text{old}} \to C_{\text{old,new}} \to C_{\text{new}}$) and single-server atomic transitions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Formal Verification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TLA+ specifications for core single-decree Paxos; Multi-Paxos implementations frequently diverge from spec.&lt;/td&gt;
&lt;td&gt;Verified in &lt;strong&gt;TLA+&lt;/strong&gt;, Coq, and rigorously tested in production via Jepsen.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  5. Production Failure Modes &amp;amp; Jepsen Chaos Engineering
&lt;/h2&gt;

&lt;p&gt;In mission-critical infrastructure, subtle edge-case partitions can trick consensus algorithms into returning stale data or corrupting state machines.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    subgraph NetworkPartition["Asymmetric Network Partition (3 vs 2 Split)"]
        subgraph MajorityPartition["Majority Partition (Quorum = 3)"]
            NodeB["Node B (New Leader, Term 2)"]
            NodeC["Node C (Follower)"]
            NodeD["Node D (Follower)"]
        end

        subgraph MinorityPartition["Minority Partition (Isolated)"]
            NodeA["Node A (Stale Leader, Term 1)"]
            NodeE["Node E (Follower)"]
        end
    end

    ClientW["Client Write"] --&amp;gt;|Rejected: No Quorum| NodeA
    ClientR["Client Read (Stale!)"] -.-&amp;gt;|Stale Read Risk without ReadIndex| NodeA
    ClientW2["Client Write"] --&amp;gt;|Committed: 3/5 Majority| NodeB&lt;/code&gt;&lt;/pre&gt;






&lt;h3&gt;
  
  
  Failure Mode 1: The Phantom Leader &amp;amp; Stale Reads
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Scenario:&lt;/strong&gt;&lt;br&gt;
A network partition isolates Node A (the Term 1 Leader) and Node E from the rest of the cluster (Nodes B, C, D). Nodes B, C, and D elect Node B as the Term 2 Leader.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Writes&lt;/strong&gt;: When a client sends a write to Node A, Node A attempts to replicate to Node E, achieves only $2/5$ votes, and &lt;strong&gt;cannot commit the write&lt;/strong&gt;. Safety is preserved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reads&lt;/strong&gt;: If a client sends a read query to Node A, and Node A naively reads its local state machine without talking to peers, it will return &lt;strong&gt;stale data&lt;/strong&gt; because Node B is actively committing new writes in Term 2!&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  The Fix: The ReadIndex &amp;amp; LeaseRead Protocols
&lt;/h4&gt;

&lt;p&gt;To maintain strict linearizability ($O(1)$ read latency without writing to disk):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ReadIndex Protocol&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;When a read request arrives at the Leader, it records its current &lt;code&gt;commitIndex&lt;/code&gt; as &lt;code&gt;readIndex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The Leader sends a heartbeat (empty &lt;code&gt;AppendEntries&lt;/code&gt;) to a majority of nodes to confirm it is still the legitimate leader.&lt;/li&gt;
&lt;li&gt;Once confirmed, the Leader waits until its state machine has applied at least up to &lt;code&gt;readIndex&lt;/code&gt;, and then returns the state machine value to the client.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leader Leases&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;The Leader assumes it retains leadership for a bounded lease duration (e.g., $100\text{ms}$) as long as followers do not start new elections.&lt;/li&gt;
&lt;li&gt;If local clocks have bounded drift, the Leader can serve linearizable reads locally during the lease window without network round-trips.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  Failure Mode 2: Disruptive Server &amp;amp; Pre-Vote Protocol
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Scenario:&lt;/strong&gt;&lt;br&gt;
Node E is partitioned from the cluster. Its election timer expires. It increments its term ($\text{Term} \to 3$), broadcasts &lt;code&gt;RequestVote&lt;/code&gt;, receives no responses, times out, increments again ($\text{Term} \to 4 \dots 10$).&lt;/p&gt;

&lt;p&gt;When the network partition heals, Node E broadcasts &lt;code&gt;RequestVote(Term=10)&lt;/code&gt; to the cluster. When the healthy Leader (Node B, Term 2) receives Term 10, it is forced to &lt;strong&gt;step down to Follower&lt;/strong&gt;, disrupting the entire cluster’s active throughput!&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant NodeE as Partitioned Node E
    participant NodeB as Healthy Leader (Term 2)
    participant NodeC as Follower C (Term 2)

    Note over NodeE: Pre-Vote Protocol Active!
    NodeE-&amp;gt;&amp;gt;NodeB: PreVoteRequest(NextTerm=3, LastLogIdx=4)
    NodeE-&amp;gt;&amp;gt;NodeC: PreVoteRequest(NextTerm=3, LastLogIdx=4)
    Note over NodeB,NodeC: Reject PreVote: Heartbeats are active!
    NodeB--&amp;gt;&amp;gt;NodeE: PreVoteDenied
    NodeC--&amp;gt;&amp;gt;NodeE: PreVoteDenied
    Note over NodeE: Term is NOT incremented! Cluster is NOT disrupted!&lt;/code&gt;&lt;/pre&gt;



&lt;h4&gt;
  
  
  The Fix: The Pre-Vote Phase
&lt;/h4&gt;

&lt;p&gt;Before a node increments its &lt;code&gt;currentTerm&lt;/code&gt;, it enters a &lt;strong&gt;&lt;code&gt;Pre-Candidate&lt;/code&gt;&lt;/strong&gt; state and sends a &lt;code&gt;PreVote&lt;/code&gt; RPC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Peers grant a &lt;code&gt;PreVote&lt;/code&gt; &lt;strong&gt;only&lt;/strong&gt; if:

&lt;ol&gt;
&lt;li&gt;The candidate’s log is at least as up-to-date as theirs.&lt;/li&gt;
&lt;li&gt;The peer has not heard from a valid leader for longer than the minimum election timeout.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Because healthy followers are actively receiving heartbeats from Node B, they reject Node E's &lt;code&gt;PreVote&lt;/code&gt;. Node E never increments its term, and the active leader is &lt;strong&gt;never disrupted&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Implementation: Production-Grade Raft Node in Go
&lt;/h2&gt;

&lt;p&gt;Below is a fully functional, concurrency-safe, production-grade implementation of a Raft Consensus Engine featuring &lt;strong&gt;Role State Transitions&lt;/strong&gt;, &lt;strong&gt;Randomized Election Timers&lt;/strong&gt;, &lt;strong&gt;Vote Counting&lt;/strong&gt;, and &lt;strong&gt;AppendEntries Heartbeats&lt;/strong&gt; in Go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;raft&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"math/rand"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Role&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Follower&lt;/span&gt; &lt;span class="n"&gt;Role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;
    &lt;span class="n"&gt;Candidate&lt;/span&gt;
    &lt;span class="n"&gt;Leader&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;Role&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Follower&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"FOLLOWER"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Candidate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"CANDIDATE"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Leader&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"LEADER"&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"UNKNOWN"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// LogEntry encapsulates a replicated state command&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;LogEntry&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Index&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Term&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Command&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// RequestVoteArgs RPC payload&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;RequestVoteArgs&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Term&lt;/span&gt;         &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;CandidateID&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;LastLogIndex&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;LastLogTerm&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// RequestVoteReply RPC response&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;RequestVoteReply&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Term&lt;/span&gt;        &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;VoteGranted&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// AppendEntriesArgs RPC payload&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;AppendEntriesArgs&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Term&lt;/span&gt;         &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;LeaderID&lt;/span&gt;     &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;PrevLogIndex&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;PrevLogTerm&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Entries&lt;/span&gt;      &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;LogEntry&lt;/span&gt;
    &lt;span class="n"&gt;LeaderCommit&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// AppendEntriesReply RPC response&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;AppendEntriesReply&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Term&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Success&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// RaftNode represents an active consensus node&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;RaftNode&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;        &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
    &lt;span class="n"&gt;peers&lt;/span&gt;     &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;
    &lt;span class="n"&gt;nodeID&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;      &lt;span class="n"&gt;Role&lt;/span&gt;

    &lt;span class="c"&gt;// Persistent State&lt;/span&gt;
    &lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;votedFor&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;         &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;LogEntry&lt;/span&gt;

    &lt;span class="c"&gt;// Volatile State&lt;/span&gt;
    &lt;span class="n"&gt;commitIndex&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;lastApplied&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

    &lt;span class="c"&gt;// Leader-specific Volatile State&lt;/span&gt;
    &lt;span class="n"&gt;nextIndex&lt;/span&gt;  &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;matchIndex&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;

    &lt;span class="c"&gt;// Timers &amp;amp; Triggers&lt;/span&gt;
    &lt;span class="n"&gt;heartbeatInterval&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;
    &lt;span class="n"&gt;electionResetTime&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;               &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;
    &lt;span class="n"&gt;cancel&lt;/span&gt;            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CancelFunc&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// NewRaftNode initializes a consensus actor&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewRaftNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peersCount&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;              &lt;span class="n"&gt;Follower&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;currentTerm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;votedFor&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;               &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;LogEntry&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;Index&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Term&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"INIT_ROOT"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
        &lt;span class="n"&gt;commitIndex&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;lastApplied&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;nextIndex&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;matchIndex&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;heartbeatInterval&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;               &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resetElectionTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;runElectionTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetPeers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;peers&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;peers&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;resetElectionTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Uniform random timeout: 150ms to 300ms&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;150&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;150&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;electionResetTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;runElectionTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ticker&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewTicker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;Leader&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;electionResetTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startElection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;startElection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Candidate&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;votedFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resetElectionTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt;
    &lt;span class="n"&gt;lastLogIdx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;lastLogTerm&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lastLogIdx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[Node %d] Election timeout! Starting election for Term %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;votesReceived&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;voteMu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;RequestVoteArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Term&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;CandidateID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;LastLogIndex&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;lastLogIdx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;LastLogTerm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;lastLogTerm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestVote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;
                &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Follower&lt;/span&gt;
                &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;votedFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
                &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resetElectionTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Candidate&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VoteGranted&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;voteMu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;votesReceived&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
                &lt;span class="n"&gt;currentVotes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;votesReceived&lt;/span&gt;
                &lt;span class="n"&gt;voteMu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

                &lt;span class="c"&gt;// Quorum achieved: majority = (N / 2) + 1&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;currentVotes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;Leader&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Leader&lt;/span&gt;
                    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"⚡ [Node %d] WON ELECTION! Became LEADER for Term %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;matchIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;runHeartbeatBroadcaster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RequestVote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="n"&gt;RequestVoteArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RequestVoteReply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// 1. Term check&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Follower&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;votedFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;RequestVoteReply&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VoteGranted&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// 2. Voting safety conditions&lt;/span&gt;
    &lt;span class="n"&gt;lastLogIdx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;lastLogTerm&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lastLogIdx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;
    &lt;span class="n"&gt;logOk&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastLogTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;lastLogTerm&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastLogTerm&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;lastLogTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastLogIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;lastLogIdx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;votedFor&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;votedFor&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CandidateID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;logOk&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VoteGranted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;votedFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CandidateID&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resetElectionTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[Node %d] Voted for Node %d in Term %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CandidateID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;runHeartbeatBroadcaster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ticker&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewTicker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heartbeatInterval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;Leader&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="n"&gt;prevIdx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
                    &lt;span class="n"&gt;prevTerm&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;prevIdx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;
                    &lt;span class="n"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

                    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;AppendEntriesArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;Term&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;LeaderID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;PrevLogIndex&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prevIdx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;PrevLogTerm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;prevTerm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Entries&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;LeaderCommit&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commitIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

                    &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppendEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;
                        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Follower&lt;/span&gt;
                        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;votedFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
                        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resetElectionTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;

                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Leader&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prevIdx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
                            &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;matchIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="c"&gt;// Step back nextIndex on mismatch&lt;/span&gt;
                            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
                            &lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RaftNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;AppendEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="n"&gt;AppendEntriesArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;AppendEntriesReply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;AppendEntriesReply&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Follower&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;votedFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resetElectionTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Verify log consistency at PrevLogIndex&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrevLogIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrevLogIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Term&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrevLogTerm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Append any new entries not already in local log&lt;/span&gt;
    &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrevLogIndex&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entries&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LeaderCommit&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commitIndex&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commitIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LeaderCommit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Real-World Implementations: Spanner vs. etcd vs. CockroachDB vs. KRaft
&lt;/h2&gt;



&lt;pre data-lang="mermaid"&gt;&lt;code&gt;graph TD
    A[Production Distributed Systems] --&amp;gt; B[Spanner: Multi-Paxos + TrueTime]
    A --&amp;gt; C[etcd: Core Raft Quorum]
    A --&amp;gt; D[CockroachDB: Multi-Raft Partition Ranges]
    A --&amp;gt; E[Kafka KRaft: Event Log Quorum Controller]

    B --&amp;gt; B1[External Consistency via GPS Atomic Clocks]
    C --&amp;gt; C1[Kubernetes Single-State Coordinator]
    D --&amp;gt; D1[Millions of 64MB Consensus Ranges]
    E --&amp;gt; E1[Replaces ZooKeeper with In-Memory Raft Event Log]&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  1. Google Spanner: Multi-Paxos with TrueTime
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Architecture&lt;/strong&gt;: Spanner groups spans of data into Paxos consensus groups replicated across continents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Linearizability Trick&lt;/strong&gt;: Instead of executing Raft ReadIndex round-trips for every cross-region read, Spanner uses &lt;strong&gt;TrueTime&lt;/strong&gt; (GPS receivers and atomic clocks in data centers with bounded uncertainty $[\text{earliest}, \text{latest}]$).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit-Wait&lt;/strong&gt;: Spanner waits out the clock uncertainty $\epsilon$ (typically $&amp;lt; 7\text{ms}$) before committing a write, guaranteeing that read transactions at timestamp $T$ reflect all writes committed before $T$ without running read-phase consensus!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. etcd: The Engine Behind Kubernetes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Architecture&lt;/strong&gt;: Implements Diego Ongaro’s Raft in pure Go (&lt;code&gt;go.etcd.io/raft&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design Philosophy&lt;/strong&gt;: Minimalist, single-Raft cluster (typically 3 or 5 nodes). Every Kubernetes resource create/update/delete passes through etcd's linearizable log.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage&lt;/strong&gt;: Backed by &lt;strong&gt;bbolt&lt;/strong&gt; (B+ Tree copy-on-write key-value store) with automatic MVCC revisions and memory-mapped snapshotting.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. CockroachDB &amp;amp; TiKV: Multi-Raft Range Architectures
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Scaling Problem&lt;/strong&gt;: A single Raft group cannot scale past one machine's disk I/O throughput.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Solution (Multi-Raft)&lt;/strong&gt;: CockroachDB splits the global keyspace into &lt;strong&gt;64MB ranges&lt;/strong&gt;. Each 64MB range forms an independent, isolated Raft consensus group across 3 nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale&lt;/strong&gt;: A 100-node CockroachDB cluster manages over &lt;strong&gt;500,000 independent concurrent Raft groups&lt;/strong&gt;, balancing throughput and leader leases across hardware CPU cores.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Apache Kafka: KRaft (KIP-500)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The ZooKeeper Bottleneck&lt;/strong&gt;: ZooKeeper stored partition metadata outside Kafka, requiring slow external synchronization that limited clusters to ~200,000 partitions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KRaft (Kafka Raft Metadata Mode)&lt;/strong&gt;: Integrates an event-driven Raft quorum directly into the Kafka broker JVM. Metadata updates are written as standard Kafka event log records, scaling clusters to &lt;strong&gt;millions of partitions&lt;/strong&gt; with sub-second controller failover.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Architectural Summary &amp;amp; Decision Framework
&lt;/h2&gt;



&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    Start[Choose Consensus Architecture] --&amp;gt; Q1{Is Global Scalability &amp;gt; 100k writes/sec required?}

    Q1 -- Yes --&amp;gt; MultiRaft[Multi-Raft Range Architecture\nCockroachDB / TiKV / Spanner]
    Q1 -- No --&amp;gt; Q2{Do you have hardware atomic clocks?}

    Q2 -- Yes --&amp;gt; PaxosTrueTime[Multi-Paxos + TrueTime Leases\nGoogle Spanner]
    Q2 -- No --&amp;gt; Q3{Is implementation clarity &amp;amp; verifiability paramount?}

    Q3 -- Yes --&amp;gt; Raft[HashiCorp / etcd Raft\netcd, Consul, Kafka KRaft]
    Q3 -- No --&amp;gt; ClassicPaxos[Custom Multi-Paxos Engine]&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  Key Engineering Takeaways:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Mathematical Equivalence, Divergent Usability&lt;/strong&gt;: Raft and Multi-Paxos provide the identical safety invariants for Replicated State Machines. Raft's structural decomposition of Leader Election, Contiguous Log Replication, and Joint Consensus avoids the edge-case state-space explosion inherent in Multi-Paxos hole-filling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read Linearizability is Not Free&lt;/strong&gt;: Naive local reads on consensus leaders violate linearizability during network partitions. Production engines must enforce &lt;strong&gt;ReadIndex quorum verification&lt;/strong&gt;, &lt;strong&gt;Pre-Vote protocols&lt;/strong&gt;, or &lt;strong&gt;synchronized physical clock leader leases&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consensus Must Be Sharded&lt;/strong&gt;: Production distributed databases never run a single global consensus loop. They employ &lt;strong&gt;Multi-Raft architectures&lt;/strong&gt;, partitioning the global keyspace into thousands of discrete, localized state machines.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  9. Architectural FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Why do consensus clusters almost always use 3, 5, or 7 nodes?&lt;/strong&gt;&lt;br&gt;
Consensus quorums require a strict majority $\lfloor N/2 \rfloor + 1$. A 3-node cluster tolerates 1 failure ($3 - 2 = 1$). A 4-node cluster still requires 3 votes for a majority, tolerating the exact same 1 failure as a 3-node cluster while adding network overhead. Odd numbers ($2F + 1$) maximize fault tolerance per node cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can a Raft leader commit an entry from a previous term directly?&lt;/strong&gt;&lt;br&gt;
No! Section 5.4.2 of the Raft paper demonstrates that a Leader cannot determine commitment of an older entry simply by counting replicas. The Leader &lt;strong&gt;must commit an entry from its own current term&lt;/strong&gt; by replicating it to a majority, which indirectly commits all preceding entries by the Log Matching Property.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the difference between Linearizability and Serializability?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serializability&lt;/strong&gt;: A multi-transaction property (from ACID). It guarantees that concurrent transactions yield the same final state as some sequential execution, but allows arbitrary time skew (historical reads).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linearizability&lt;/strong&gt;: A single-operation, real-time recency guarantee. If operation $B$ starts after operation $A$ completes in physical time, $B$ must see $A$’s result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict Serializability (External Consistency)&lt;/strong&gt;: The gold standard combining both properties (achieved by Spanner and CockroachDB).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>database</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>I built a terminal dashboard for managing Python project tasks</title>
      <dc:creator>Shinde Aditya</dc:creator>
      <pubDate>Tue, 04 Aug 2026 20:15:29 +0000</pubDate>
      <link>https://dev.to/heyshinde/i-built-a-terminal-dashboard-for-managing-python-project-tasks-3l2l</link>
      <guid>https://dev.to/heyshinde/i-built-a-terminal-dashboard-for-managing-python-project-tasks-3l2l</guid>
      <description>&lt;p&gt;Over the past few weeks I’ve been working on a small tool called TermBoard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzue4hpyl6e3i6gzwdsyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzue4hpyl6e3i6gzwdsyw.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s a terminal dashboard for running project tasks without having to remember how each project is set up.&lt;/p&gt;

&lt;p&gt;One project uses uv, another uses poetry, another has a plain virtual environment, and before long I find myself checking the README just to remember how to run tests or start the application.&lt;/p&gt;

&lt;p&gt;TermBoard tries to remove that friction.&lt;/p&gt;

&lt;p&gt;It automatically detects the Python environment for the current project and runs tasks in the right environment. At the moment it supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;uv&lt;/li&gt;
&lt;li&gt;poetry&lt;/li&gt;
&lt;li&gt;pipenv&lt;/li&gt;
&lt;li&gt;standard .venv&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of opening multiple terminals, tasks run in the background and their logs appear in a scrollable panel inside the dashboard. That means I can keep an eye on several long running commands without filling my terminal history with thousands of log lines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5kgw3n0hb99urt01nscy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5kgw3n0hb99urt01nscy.png" alt=" " width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configuration is done with a simple termboard.toml file, so adding project specific tasks is straightforward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldv3jd0mc7pw0gv9z0qo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldv3jd0mc7pw0gv9z0qo.png" alt=" " width="799" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is built with the Textual framework, which made it possible to build a terminal interface that still feels responsive while multiple tasks are running.&lt;/p&gt;

&lt;p&gt;If you’re happy with make, just, or shell scripts, those tools are great. TermBoard isn’t trying to replace them. It’s more about giving those tasks a persistent interface where you can start, stop, monitor, and inspect them from one place.&lt;/p&gt;

&lt;p&gt;If you’d like to try it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv tool &lt;span class="nb"&gt;install &lt;/span&gt;termboard
&lt;span class="c"&gt;# or&lt;/span&gt;
pipx &lt;span class="nb"&gt;install &lt;/span&gt;termboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/HeyShinde/TermBoard" rel="noopener noreferrer"&gt;https://github.com/HeyShinde/TermBoard&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation: &lt;a href="https://heyshinde.github.io/TermBoard/" rel="noopener noreferrer"&gt;https://heyshinde.github.io/TermBoard/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is still evolving, so I’d genuinely appreciate feedback. If there’s something that would make your own workflow easier, I’d love to hear about it.&lt;/p&gt;

</description>
      <category>python</category>
      <category>terminal</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
