Skip to main content

Open source · .NET · self-hosted cluster

Coordinate work across your services

An easy-to-use distributed systems toolkit. Give one worker ownership of a job, keep shared data consistent, and allocate IDs safely across services with distributed locks, a consistent key/value store, and ordered ID sequences.

Built for mission-critical applications, with automatic failover and online scaling. One coordination layer for .NET and TypeScript, with less glue code to maintain across Redis and an RDBMS.

Distributed locks
Consistent key/value store
Ordered ID sequences
Jepsen-tested

Why Kahuna

Give your services a shared source of truth

When multiple workers act on the same data, they need to agree on ownership, updates, and retries. Kahuna provides those building blocks—and keeps them replicated as your application grows.

One worker per job

Use leases and fencing tokens to give one worker ownership of a job or tenant.

Consistent shared state

Read current revisions and use transactional compare-and-set for workflows like rate limiting.

Safe, ordered IDs

Allocate numbers and ranges across nodes without races, with idempotent retries.

Built for 24/7 applications

Replicate persistent state through Raft and recover automatically from a leader failure. A three-replica partition can tolerate one failed replica and resume work after election while a majority remains available.

Explore failure recovery →

Grow your cluster online

Add nodes to a running cluster. With replica placement and rebalancing enabled, Kahuna copies partitions to new nodes in the background, then promotes replicas once they catch up.

Explore horizontal scaling →

Less coordination glue to maintain

Keep critical locks, shared state, and sequences in one consistent system, instead of maintaining coordination logic across Redis and an RDBMS. Keep your relational database for business data and queries.

Why choose Kahuna? →

Custom C# logic

Run trusted C# functions inside Kahuna Script transactions for validation and business rules.

Learn about user-defined functions →

Fast enough for hot paths

Single-node can reach 290k req/s for ephemeral workloads

See benchmark details →

Your choice of storage

Choose RocksDB, SQLite, or memory, or run the data store and Raft log on Solarium through an external extension.

Explore the Solarium integration →

Inside Kahuna

Follow one request, step by step​

Choose a task, then step through it at your own pace. Each numbered message shows who sends what. These are illustrated examples of persistent operations, not a live cluster.

LockingStep 1 of 6

Both apps ask for the same lock

App A and App B both ask to lock “invoice-2048”. Their requests reach the Kahuna server in charge of that lock: its leader.

Inspect state on each node
App node A
Asking for lock
App node B
Asking for lock
Kahuna 1
Lock is free
Kahuna 2
Lock is free
Kahuna 3
Lock is free
  1. App node A → Kahuna 1Lock invoice-2048
  2. App node B → Kahuna 1Lock invoice-2048

Leader = server handling this key. Replicas = servers keeping copies. Highlighted cards take part in this step.

Same lock: invoice-2048

The scenario

Two apps. One lock. One winner.

Both app nodes want to process the same invoice. A lock lets only one own the job at a time.

What to remember

The lock’s owner is copied across Kahuna servers. Both apps get an answer from the same leader.

Learn about locks →

Where it fits

Use it for shared ownership and control-plane work

Fewer duplicate workers, fewer stale writes, fewer homegrown coordination paths

Good fit

  • Mission-critical services that run around the clock
  • Growing workloads that need online cluster expansion
  • Distributed locking for critical sections
  • Reliable shared configuration and metadata
  • Ordered ID allocation across nodes
  • Custom C# functions inside transactions
  • Multi-step workflows with compare-and-set
  • Services that need quorum-backed coordination
  • MIT-licensed Kahuna with no proprietary runtime fees

Not the target

  • A general-purpose analytics database
  • A document store for large unstructured datasets
  • Fire-and-forget eventually consistent pipelines
  • Single-node apps that do not need quorum or leader election

Example

The same code on one node or a full cluster

Start with one node on your laptop. To move to a replicated cluster, add endpoints. Pick a building block to see the client code.

InvoiceWorker.cs1 node
using Kahuna.Client;


var client = new KahunaClient("https://localhost:8082");


await using KahunaLock jobLock = await client.GetOrCreateLock(
    "jobs/invoice-2048",
    expiry: TimeSpan.FromSeconds(30),
    wait: TimeSpan.FromSeconds(5),
    retry: TimeSpan.FromMilliseconds(200)
);


if (jobLock.IsAcquired)
{
    // Pass the token to the resource you protect
    await ProcessInvoice(2048, jobLock.FencingToken);
}


// The lock is released when jobLock is disposed
Only the highlighted connection changes between a single node and a cluster.

What this buys you

  • Only one worker processes the invoice. Others wait up to 5 seconds, then give up.
  • The lease expires after 30 seconds if the owner crashes, so the job never stays stuck.
  • Each acquisition gets a fencing token, so the resource can reject writes from a former owner.
Read the locks guide →

One node for development and tests

  • Start one container and connect to one endpoint.
  • Persistent data goes to disk, but there are no replicas: if the node stops, the data is unavailable until it restarts.
  • Use it for local development, CI, and workloads that can accept downtime.
docker run --rm -p 8082:8082 -v kahuna-data:/data kahunakv/kahuna:latest