Skip to content

Repository files navigation

rafter

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


Model

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 checking

Use 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.

API Layers

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.

Example

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);
        }
        _ => {}
    }
}

Crates

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

Reference Consumers

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.

Testing

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-check

The 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.

Benchmarks

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-cluster

The 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.

Boundaries

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 validation

Status

Rafter is pre-1.0. The core invariants, durable formats, simulation coverage, and Maelstrom tests are treated seriously; APIs are still expected to move.

License

Licensed under Apache-2.0. See LICENSE and NOTICE.