Skip to main content

Open-source Raft for C# and .NET

Make your .NET services agree, and survive failure

Kommander is an embedded library that lets several nodes commit the same ordered stream of changes, so your system keeps one source of truth even when nodes restart or the network breaks. You keep your data model and APIs. It handles leader election, replication, and durable recovery.

// Only the leader for a partition can propose. The change is
// committed once a quorum of nodes has durably stored it.
if (await raft.AmILeader(partitionId, ct))
{
RaftReplicationResult result = await raft.ReplicateLogs(
partitionId,
"OrderPlaced",
payload,
cancellationToken: ct
);
Console.WriteLine($"Committed at log #{result.LogIndex}");
}
// Every node applies committed entries in the same order,
// so the whole cluster ends up with one source of truth.
raft.OnReplicationReceived += (partitionId, log) => Apply(log.LogData);
Partitioned Raft groups
Dynamic membership
Elastic partitions
Embedded in your .NET service
gRPC, REST, or in-memory transport
MIT-licensed for commercial and internal use

Why teams use it

Consensus mechanics without handing your system over to a black box

Kommander is a library, not a finished database product. That is the point: it gives you the hard distributed-systems machinery while keeping your service architecture, data model, and APIs in your hands

Spread writes across partitions

Different partitions can have different leaders, so one node does not have to own every write in the cluster.

Keep control of your domain model

Kommander gives you consensus, WAL durability, and leader election. Your service keeps the API, schema, authorization, and business logic.

Run it where your service already runs

Use it as a library inside an ASP.NET Core host instead of standing up a separate control-plane product just to coordinate state.

Choose the durability and transport path

Use RocksDB or SQLite in production, in-memory adapters in tests, and gRPC or REST depending on how your cluster is hosted.

Scale partitions at runtime

Create, split, merge, and remove user partitions without restarting the cluster, with generation fencing to protect callers from stale routing.

Change cluster membership safely

Add nodes as learners, promote them after catch-up, and remove members through the committed system partition roster instead of trusting discovery snapshots.

Debug real runtime behavior

Queue-depth metrics, operation latency, WAL batching telemetry, stale-completion counters, and deterministic simulation tooling make failures easier to explain.

What it is

A serious foundation for replicated control-plane work

Use Kommander when several machines need to agree on the same ordered stream of decisions and another node must be able to continue safely after a failure.

Good fit

  • Replicated control planes
  • Partitioned metadata services
  • Leader-owned workers and schedulers
  • Workflow and job coordination
  • Embedded coordination inside .NET services

Not the target

  • A finished database product
  • A drop-in cache or queue
  • Eventually consistent fire-and-forget workloads
  • Single-node applications that do not need quorum safety

What you get

The value is not just Raft. It is the runtime around Raft

Partition executors, fair schedulers, WAL adapters, transport choices, lifecycle APIs, security controls, and diagnostics make the library usable in real services instead of only in toy examples.

Elastic partitions

Create partitions for new workloads, split hot ranges, merge cooled ranges, and fence stale callers with partition generations while your service keeps ownership of state-transfer behavior.

Read the partition guide

Dynamic membership

Join new nodes as non-voting learners, promote them after they catch up, and remove members through a committed roster on the system partition so quorum is based on consensus, not discovery.

Read the membership guide

Operational visibility

Metrics and logs explain queue pressure, operation latency, WAL batching, stale completions, and election behavior, while deterministic simulation helps reproduce timing-sensitive failures.