RepoPilotOpen in app →

hashicorp/raft

Golang implementation of the Raft consensus protocol

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 2w ago
  • 33+ active contributors
  • Distributed ownership (top contributor 14% of recent commits)
Show all 6 evidence items →
  • MPL-2.0 licensed
  • CI configured
  • Tests present

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/hashicorp/raft)](https://repopilot.app/r/hashicorp/raft)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/hashicorp/raft on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: hashicorp/raft

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/hashicorp/raft shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 2w ago
  • 33+ active contributors
  • Distributed ownership (top contributor 14% of recent commits)
  • MPL-2.0 licensed
  • CI configured
  • Tests present

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live hashicorp/raft repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/hashicorp/raft.

What it runs against: a local clone of hashicorp/raft — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in hashicorp/raft | Confirms the artifact applies here, not a fork | | 2 | License is still MPL-2.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 43 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>hashicorp/raft</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of hashicorp/raft. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/hashicorp/raft.git
#   cd raft
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of hashicorp/raft and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "hashicorp/raft(\\.git)?\\b" \\
  && ok "origin remote is hashicorp/raft" \\
  || miss "origin remote is not hashicorp/raft (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MPL-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MPL-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is MPL-2.0" \\
  || miss "license drift — was MPL-2.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "raft.go" \\
  && ok "raft.go" \\
  || miss "missing critical file: raft.go"
test -f "api.go" \\
  && ok "api.go" \\
  || miss "missing critical file: api.go"
test -f "replication.go" \\
  && ok "replication.go" \\
  || miss "missing critical file: replication.go"
test -f "fsm.go" \\
  && ok "fsm.go" \\
  || miss "missing critical file: fsm.go"
test -f "log.go" \\
  && ok "log.go" \\
  || miss "missing critical file: log.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 43 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~13d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/hashicorp/raft"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

hashicorp/raft is a production-grade Go library implementing the Raft consensus protocol, enabling distributed systems to maintain a replicated log and replicated state machines (via FSM integration). It solves the consensus problem for building fault-tolerant, Consistent Partition-Tolerant (CP) distributed systems by managing leader election, log replication, and safety guarantees across a cluster of nodes. Monolithic single-package library structure: core interfaces and types in api.go, commands.go, fsm.go; configuration in config.go and configuration.go; multiple storage backends in-memory (inmem_store.go, inmem_snapshot.go, inmem_transport.go) and file-based (file_snapshot.go); extensive integration tests in fuzzy/ (cluster.go, transport.go, leadership_transfer_test.go, partition_test.go); benchmarks in bench/ and bench_test.go.

👥Who it's for

Go backend engineers and distributed systems architects who need to build fault-tolerant consensus-based services (e.g., Consul, Nomad, or custom distributed databases). Contributors are typically HashiCorp maintainers and community developers extending Raft with storage backends like raft-boltdb or raft-mdb.

🌱Maturity & risk

This is a production-mature, actively maintained library. It has been in use since v0.1.0 (original stable version used by Consul pre-0.7), versioned releases since September 2017 (v1.0.0+), comprehensive CI/CD via .github/workflows/ci.yml, and extensive test coverage (bench_test.go, fuzzy/ integration tests). The fuzzy testing suite and separate backend repositories (raft-boltdb, raft-mdb) indicate serious production usage and ongoing active development.

Low risk for a consensus library. The dependency surface is minimal (go-hclog, go-msgpack/v2, go-metrics), which reduces supply chain risk. However, consensus protocol implementations require expert review for correctness—any deviation from the Raft spec can cause data corruption or split-brain scenarios. The .github/dependabot.yml suggests active dependency maintenance. No obvious single-maintainer risk given HashiCorp stewardship, but consensus bugs could be silent and catastrophic.

Active areas of work

Active consensus protocol implementation maintenance and testing. The fuzzy/ subdirectory contains property-based and chaos-testing scenarios (leadership transfer, membership changes, network partitions, slow voters). CI runs via .github/workflows/ci.yml. Likely working on edge cases, network failure handling, and performance optimizations given the dedicated bench/ suite and fuzzy test coverage.

🚀Get running

Clone and run basic tests: git clone https://github.com/hashicorp/raft.git && cd raft && go test ./... && make test (Makefile available). Requires Go 1.16+; check version with go version. For fuzzy testing: cd fuzzy && go test -v ./...

Daily commands: go test ./... runs unit tests (no external services required). go test -run Benchmark -bench=. ./bench runs benchmarks (see bench_test.go). Fuzzy integration tests: cd fuzzy && go test -v -race ./... for chaos and partition scenarios.

🗺️Map of the codebase

  • raft.go — Main Raft implementation and state machine orchestration; this is the entry point and core consensus logic.
  • api.go — Public API surface for applying commands, taking snapshots, and managing the Raft instance lifecycle.
  • replication.go — Log replication and peer synchronization logic; critical for maintaining cluster consistency.
  • fsm.go — Finite State Machine abstraction that defines how application state is applied from the replicated log.
  • log.go — Log entry storage and retrieval interface; foundation for durability and recovery.
  • transport.go — Network transport abstraction enabling pluggable communication backends (TCP, in-memory).
  • snapshot.go — Snapshot interface for persistent state capture and cluster bootstrap optimization.

🛠️How to make changes

Add a Custom Transport Backend

  1. Define a new struct that embeds or implements the Transport interface from transport.go (transport.go)
  2. Implement required methods: Open, Close, AppendEntries, RequestVote, InstallSnapshot, and EncodePeer/DecodePeer (transport.go)
  3. Pass your transport instance to NewRaft or config via the Transport field in config.go (config.go)
  4. Add tests to verify peer communication and message ordering, following the pattern in inmem_transport_test.go (inmem_transport_test.go)

Add a Custom Storage Backend

  1. Implement the LogStore interface (StoreLog, GetLog, FirstIndex, LastIndex, etc.) from log.go (log.go)
  2. Implement the StableStore interface (Set, Get, SetUint64, GetUint64) from stable.go (stable.go)
  3. Optionally implement the SnapshotStore interface from snapshot.go for persistent snapshots (snapshot.go)
  4. Pass your store instances to NewRaft via the Logs, Stable, and Snapshots fields in config.go (config.go)

Implement a Custom FSM for Your Application

  1. Create a struct that implements the FSM interface from fsm.go (Apply and Snapshot methods) (fsm.go)
  2. In Apply, decode the Command bytes from the Log entry (typically using msgpack via commands.go patterns) (commands.go)
  3. Update your application's in-memory state based on the command type and return an error or opaque response (fsm.go)
  4. Implement Snapshot to return a snapshot of current state using the SnapshotSink interface (snapshot.go)
  5. Pass your FSM instance to NewRaft via the FSM field in config.go (config.go)

Monitor Cluster Health and Replication Progress

  1. Use Observer interface (observer.go) to register observers that receive state transitions and term changes (observer.go)
  2. Call GetStats() on the Raft instance to retrieve leadership, commit index, and applied index metrics (api.go)
  3. For peer-specific progress, access the Progress field on each peer via internal replication state or extend progress.go (progress.go)

🔧Why these technologies

  • Go — Efficient concurrency primitives (goroutines, channels) for managing multiple peer connections and timers simultaneously; straightforward serialization with msgpack.
  • Pluggable Storage (LogStore, StableStore, SnapshotStore) — Decouples consensus logic from persistence, enabling users to swap backends (e.g., BoltDB, RocksDB) without modifying Raft internals.
  • Pluggable Transport (net_transport, inmem_transport) — Allows testing in-memory without network overhead and enables custom transport protocols (gRPC, QUIC) by implementing the Transport interface.
  • Log Cache (log_cache.go) — Reduces I/O latency for frequently-accessed recent log entries, improving replication speed and recovery performance.

⚖️Trade-offs already made

  • Single-threaded event loop per Raft instance vs. fully concurrent goroutines per peer

    • Why: Simplified reasoning about term updates and state transitions; avoids complex locking on the core consensus state.
    • Consequence: Leadership and replication are high-volume operations; CPU-intensive replication can block election timers if not careful. Mitigated by efficient log caching and batch replication.
  • Async Apply futures instead of blocking consensus

    • Why: Non-blocking API allows client applications to overlap requests; improves throughput and responsiveness.
    • Consequence: Client must handle out-of-order completions and manage future lifecycle; increased complexity for applications.
  • Snapshots stored separately from log

    • Why: Decouples state persistence from log compaction; enables faster cluster bootstrap and smaller log files.
    • Consequence: Requires coordination between log and snapshot stores during recovery; more complex state machine integration.
  • Peer-to-peer replication without a central coordination point

    • Why: Standard Raft design; resilient to leader failures and enables parallel replication to multiple peers.
    • Consequence: More complex state tracking (next_index, match_index per peer); increased memory overhead on leaders with many followers.

🚫Non-goals (don't propose these)

  • Automatic leader re-election without manual intervention or monitoring (relies on application to detect stale leadership)
  • Built-in authentication or encryption for inter-node communication (delegated to Transport implementations)
  • Multi-raft instances with shared state (each instance is independent; coordination must happen at the application layer)
  • Automatic data repair or anti-entropy beyond log replication (assumes persistent storage is reliable)
  • Sub-millisecond consensus latency (typical commit latency is 10-100ms per RPC round trip)

🪤Traps & gotchas

No required env vars, but several subtle design constraints: (1) FSM.Apply() is called serially per log index—blocking here blocks replication; (2) The LogStore and StableStore must persist synchronously (writes must hit disk before RPC responses), or split-brain is possible; (3) Network partitions and leadership/follower role transitions are asynchronous—state races are easy to miss in testing; (4) The fuzzy/ tests require understanding of cluster simulation (cluster.go, node.go, verifier.go) to debug failures; (5) Configuration changes (add/remove peer) use two-phase commit under the hood (configuration.go), not obvious from API.

🏗️Architecture

💡Concepts to learn

  • Raft Consensus Protocol — This library is a direct implementation of Raft; you must understand leader election, log replication, safety/liveness properties, and the RequestVote/AppendEntries RPC protocol to debug consensus failures.
  • Finite State Machine (FSM) Abstraction — Raft replicates a log that is applied to an FSM (fsm.go); your business logic lives in the FSM implementation, not in Raft itself. The serial Apply() contract is non-negotiable.
  • Log Replication & Commit Guarantees — commitment.go implements the safety property that entries are only applied once replicated to a quorum. Misunderstanding commit indices leads to data loss or split-brain.
  • Pluggable Storage Backends (LogStore/StableStore) — api.go defines interfaces for log and stable storage; the in-memory implementations (inmem_store.go) are for testing only. Production requires persistent backends (raft-boltdb, raft-mdb).
  • Transport Abstraction & RPC — The Transport interface (api.go) is pluggable; inmem_transport.go is for testing, but production uses gRPC or custom transports. Network failures directly impact Raft safety.
  • Configuration Changes (Membership) — configuration.go implements two-phase peer addition/removal to avoid split-brain during cluster scaling. Not handling this correctly causes data corruption.
  • Network Partitions & Quorum Loss — fuzzy/ tests validate behavior under partitions. Raft cannot commit without a quorum, so minority partitions stall; this is by design (CP trade-off) and must be understood operationally.
  • etcd-io/etcd — Alternative Raft implementation used in etcd distributed key-value store; reference for production Raft usage patterns and comparison of go-grpc transport vs hashicorp/raft's pluggable transport.
  • hashicorp/raft-boltdb — Official pure-Go backend for raft LogStore/StableStore using Bbolt; required companion for persistent Raft deployments without cgo.
  • hashicorp/raft-mdb — Recommended production backend for raft using LMDB; mentioned in README as primary MDBStore implementation to avoid cgo complications.
  • hashicorp/consul — Major real-world user of hashicorp/raft; demonstrates how to build a distributed service discovery system on top of Raft consensus.
  • hashicorp/nomad — Another HashiCorp project using raft for cluster state management; shows Raft usage in a workload orchestrator.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for log_cache.go

log_cache.go exists but log_cache_test.go likely has incomplete coverage. The log cache is critical for Raft performance (reduces disk I/O). A new contributor could add tests for edge cases like cache eviction, concurrent access patterns, and boundary conditions around cache size limits. This directly improves reliability of a hot code path.

  • [ ] Review existing log_cache_test.go to identify untested functions and edge cases
  • [ ] Add tests for concurrent reads/writes to the cache
  • [ ] Add tests for cache eviction policies and size boundaries
  • [ ] Add benchmarks comparing cached vs non-cached log operations
  • [ ] Run 'go test -cover' to verify >90% code coverage for log_cache.go

Implement missing snapshot storage backend tests in file_snapshot_test.go

The repo has inmem_snapshot_test.go and file_snapshot_test.go, but file-based snapshots have more complexity (disk I/O, file permissions, concurrent access, corrupted files). A new contributor could add integration tests for scenarios like disk full, permission denied, partial writes, and recovery from corrupted snapshots—critical for production reliability.

  • [ ] Review file_snapshot.go to understand current implementation
  • [ ] Add tests for file permission errors and recovery
  • [ ] Add tests for partial/corrupted snapshot file handling
  • [ ] Add tests for concurrent snapshot reads and writes
  • [ ] Add tests for disk space exhaustion scenarios
  • [ ] Verify file cleanup happens properly in all error paths

Add CI workflow for Go 1.24 compatibility testing and add compat tests to CI pipeline

The fuzzy/go.mod specifies Go 1.24.0, but .github/workflows/ci.yml likely only tests stable Go versions. Additionally, raft-compat/ directory exists with compatibility tests (prevote_test.go, rolling_upgrade_test.go) that may not be running in CI. A contributor could add a CI workflow step to run these raft-compat tests against multiple Go versions to catch version-specific regressions early.

  • [ ] Review .github/workflows/ci.yml to see current Go version matrix
  • [ ] Add raft-compat tests (cd raft-compat && go test ./...) to CI pipeline
  • [ ] Add Go 1.24 to the test matrix in ci.yml
  • [ ] Ensure fuzzy tests (cd fuzzy && go test ./...) also run in CI
  • [ ] Document any version-specific constraints in README.md or CONTRIBUTING.md

🌿Good first issues

  • Add metrics instrumentation: commitment.go tracks commit indices but lacks exported counters for monitoring. Add gauges/counters to measure log length, commit index, applied index, and export via hashicorp/go-metrics.
  • Expand file_snapshot.go and inmem_snapshot.go test coverage: currently only basic tests exist. Add tests for concurrent snapshot reads/writes, corrupted snapshot recovery, and large snapshot edge cases.
  • Document FSM contract and threading model in fsm.go: the library enforces serial Apply() calls and sync persistence requirements, but no inline doc explains why or the consequences of violating them. Add detailed comments with examples.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • ce1d06b — docs: update metrics README to reflect current migration status (#677) (goingforstudying-ctrl)
  • fb8b30e — Merge pull request #675 from hashicorp/dependabot/github_actions/actions-4684ddd577 (ssagarverma)
  • 74b637f — [chore] : Bump actions/upload-artifact in the actions group (dependabot[bot])
  • 4f9dcce — Merge pull request #673 from hashicorp/dependabot/github_actions/actions-84ffaffffe (ssagarverma)
  • 3fbac0e — [chore] : Bump actions/setup-go from 6.3.0 to 6.4.0 in the actions group (dependabot[bot])
  • 80fd32e — [chore] : Bump github.com/hashicorp/go-msgpack/v2 (#672) (dependabot[bot])
  • 673fedb — CI: remove two-step-pr-approval action (#671) (tgross)
  • b9f94dd — [chore] : Bump the go group across 3 directories with 3 updates (#657) (dependabot[bot])
  • 1d4486b — CI: have the compatibility test run on supported Go versions (#670) (tgross)
  • 0f35be1 — [chore] : Bump the actions group across 1 directory with 4 updates (#659) (dependabot[bot])

🔒Security observations

The HashiCorp Raft repository has moderate security concerns primarily related to outdated and unmaintained dependencies, particularly BoltDB (v1.3.1 from 2017) and raft-boltdb. The fuzzy testing module contains dependency version conflicts and uses Go 1.24.0 which appears incorrect. While the core Raft consensus implementation is well-maintained, the dependency management requires immediate attention. The project lacks explicit security disclosure policies. Recommendations focus on updating dependencies, resolving version conflicts, and implementing proper security governance practices.

  • High · Outdated BoltDB Dependency — fuzzy/go.mod - dependency: github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea. The fuzzy/go.mod file references github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea, which is an extremely old version from October 2017. The underlying boltdb/bolt v1.3.1 dependency has known security vulnerabilities and has not been maintained since 2017. BoltDB is vulnerable to various issues including potential data corruption and security flaws in key-value storage operations. Fix: Update to the latest version of raft-boltdb and consider migrating to bbolt (github.com/etcd-io/bbolt), which is the actively maintained fork of BoltDB with security patches and bug fixes.
  • High · Outdated Go Version Target — fuzzy/go.mod - go version declaration. The fuzzy/go.mod specifies 'go 1.24.0', which appears to be a future/unreleased version. This is unusual and may indicate version inconsistency issues. The main module should use a stable, released Go version that matches the project's actual minimum supported version. Fix: Update the Go version to match the project's actual minimum supported version (e.g., 1.18 or 1.19 based on HashiCorp standards). Verify consistency across all go.mod files in the repository.
  • Medium · Duplicate go-metrics Dependency — fuzzy/go.mod - indirect dependencies: github.com/armon/go-metrics (two versions). The fuzzy/go.mod contains two different versions of go-metrics: v0.4.1 and v0.5.4 listed as indirect dependencies. This version conflict may cause inconsistent behavior and potential supply chain risks if different code paths use different versions of the same dependency. Fix: Resolve the dependency conflict by explicitly specifying a single version of github.com/armon/go-metrics in the go.mod file. Run 'go mod tidy' to clean up duplicate/conflicting dependencies.
  • Medium · Outdated Transitive Dependencies — fuzzy/go.mod - indirect dependencies: golang.org/x, mattn packages. Several transitive dependencies are significantly outdated: golang.org/x/sys v0.13.0 (from 2023), github.com/mattn/go-isatty v0.0.14 (from 2021), and github.com/mattn/go-colorable v0.1.12 (from 2021). While not directly used, these may contain known vulnerabilities. Fix: Run 'go get -u ./...' to update all transitive dependencies to their latest versions. Review security advisories using 'go list -u -m all' and 'govulncheck ./...' to identify and patch known vulnerabilities.
  • Low · Missing Security Policy — Repository root - missing SECURITY.md. The repository does not appear to have a SECURITY.md file for responsible vulnerability disclosure. This makes it difficult for security researchers to report vulnerabilities through a proper disclosure process. Fix: Create a SECURITY.md file in the repository root following GitHub's security policy template. Include instructions for responsible vulnerability disclosure, supported versions, and security contact information.
  • Low · No Code Signing Verification — .github/workflows/ci.yml (workflow configuration). The .github/workflows/ci.yml file is not visible for review, but the repository should implement GPG signing for releases and commits to ensure authenticity and prevent supply chain attacks. Fix: Implement GPG signature verification for git commits and cryptographically sign all releases. Configure GitHub branch protection rules to require signed commits on main branches.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · hashicorp/raft — RepoPilot