A deterministic Raft stack for systems that own their runtime.
Rafter gives you a sans-IO protocol core, durable storage/runtime layers, simulation tools, and small embedding crates without taking over your transport, task model, or application state machine.
Model · API Layers · Example · Crates · Reference Consumers · Testing · Benchmarks
rafter pure Raft kernel
rafter-runtime-api persist-before-output runtime boundary
rafter-storage hard-state, log, and snapshot stores
rafter-runtime durable node wrapper
rafter-app embedded state-machine layer
rafter-service async handle and transport traits
rafter-multiraft many-group host
rafter-codec peer-message wire format
rafter-sim simulation and model checkingUse the lower crates when you want full control. Use the higher crates when you want application structure without surrendering storage, transport, scheduling, identity, or recovery policy.
| Layer | Reach for it when |
|---|---|
rafter |
You want the deterministic protocol kernel and explicit outputs. |
rafter-runtime |
You want a durable persist-before-output node. |
rafter-app |
You want an embedded replicated state machine. |
rafter-service |
You want async handles and transport traits. |
rafter-multiraft |
You want many caller-defined Raft groups in one host. |
use rafter::{Input, Node, NodeConfig, NodeId, Output};
let config = NodeConfig::new(NodeId(1), vec![NodeId(2), NodeId(3)], 10)
.expect("valid raft config");
let mut node = Node::new(config);
for output in node.step(Input::Tick) {
match output {
Output::Send { to, message } => {
// route through your transport
let _ = (to, message);
}
Output::Apply { index, payload, .. } => {
// apply to your state machine
let _ = (index, payload);
}
_ => {}
}
}| Need | Crate |
|---|---|
| Protocol kernel | rafter |
| Durable node | rafter-runtime + rafter-storage |
| Embedded state machine | rafter-app |
| Async managed handle | rafter-service |
| Many Raft groups | rafter-multiraft |
| Simulation | rafter-sim |
Rafter's 1.0 plan includes three independent acceptance systems: a replicated
ledger, a fenced lock service, and a sharded counter service. They exist to
prove application durability, linearizable authority, and managed multi-group
scheduling without moving product policy into Rafter. All three use versioned
public Rafter dependencies in canonical manifests and run in source and
exact-package modes. The ledger and lock add durable process histories; the
lock also carries a bounded authenticated production-composition fixture. The
counter drives the public managed scheduler through deterministic 64, 1,024,
and 4,096-group profiles plus durable process coverage. Their contracts,
isolation rules, and executable verification lanes live in
docs/reference-consumers.md, with the stable
proof map in docs/work-completion.md.
cargo test --workspace
cargo test -p rafter-sim
cargo run --release -p rafter-sim --bin rafter-model-check-fast
cargo run --locked -p rafter-invariants -- run-all --profile pr
scripts/maelstrom-lin-kv
scripts/reference-source-check
scripts/reference-package-check
scripts/reference-package-process-checkThe reference consumers live in their own Cargo workspace, which the root
Cargo.toml excludes, so cargo test --workspace above does not reach them.
The three reference commands cover checkout-patched source, exact package
archives, and exact-package process/MSRV evidence. CI checks the deterministic
and MSRV lanes on pull requests and runs the full process lanes on main.
The repository also carries fuzz seeds, TLA+ specs, Maelstrom workloads, and a
simulation harness that can replay and explore bounded failure schedules.
The Raft verification contract lives in
docs/raft-invariants.md, generated from the
machine-readable catalog at
verification/raft-invariants.yaml.
The model-check profiles, state-count semantics, and reproducible overhead
measurement procedure are documented in
docs/model-checking.md.
run-all loads one immutable execution plan, runs every required layer, and
aggregates only the evidence produced by that invocation. check is the
separate aggregation-only command for existing result bundles. The
production run and run-all evidence subprocesses require Linux
descriptor-bound executable launch and fail closed on other operating systems.
The macOS CI lane exercises launcher mechanics under test-only fallback; it
does not produce accepted invariant evidence. The
deterministic PR aggregate emits exactly one verdict for each of the 44
reviewed IDs. Branch protection on main requires the stable invariants-pr
job; missing, malformed, incomplete, or stale evidence makes that job red.
Evidence artifacts are isolated by workflow run attempt. After a partial
GitHub Actions rerun, rerun every invariant evidence job together; a lone
aggregate rerun intentionally reports missing evidence instead of reusing a
prior attempt.
Maelstrom supplies sampled end-to-end evidence in nightly and weekly profiles
and is intentionally excluded from the deterministic PR verdict. Scheduled
invariants-nightly and invariants-weekly jobs run every required layer,
render the same 44-row report, and remain red on missing evidence or exhausted
coverage budgets.
Three-node in-memory protocol benchmark, 512-byte payloads, aarch64 Linux. Lower latency is better; higher throughput is better.
| Library | Serial props/s | Serial p99 us | Pipelined props/s | Pipelined p99 us |
|---|---|---|---|---|
rafter |
777,013 | 3.9 | 1,988,986 | 142.3 |
raft-rs |
379,723 | 7.4 | 653,298 | 234.3 |
openraft |
111,254 | 19.2 | 540,752 | 172.3 |
Results come from bench-compare/results/latest.json.
Run them locally with:
scripts/bench-compare.sh
cargo run --release -p rafter-runtime --bin rafter-bench-clusterThe comparison harness measures the in-memory protocol path. The
rafter-bench-cluster binary measures Rafter's durable runtime path, including
file-backed storage and group commit.
Rafter is not a database, a transport security layer, or a server framework. Production embeddings still own:
application state durability
applied-index recovery
peer identity and authorization
removed-peer fencing
transport encryption
snapshot validationRafter is pre-1.0. The core invariants, durable formats, simulation coverage, and Maelstrom tests are treated seriously; APIs are still expected to move.