Why Kahuna
Keep serving. Keep growing.
Availability and growth belong in the coordination layer. Kahuna handles replication, leader election, and partition placement so your team can focus on the application.
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? →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.
Custom C# logic
Run trusted C# functions inside Kahuna Script transactions for validation and business rules.
Fast enough for hot paths
Single-node can reach 290k req/s for ephemeral workloads
See benchmark details →Your choice of storage
RocksDB for heavy writes, SQLite for smaller deployments, or memory for tests and temporary state.
Inside Kahuna
Follow one request, step by step.
Choose a task, then use Next step to follow it at your own pace. Each numbered message shows who sends what. These are illustrated examples of persistent operations, not a live cluster.
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.
1. 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.
Leader = server handling this key. Replicas = servers keeping copies. Highlighted cards take part in this step.
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
Same lock: invoice-2048Jump to a step
The lock’s owner is copied across Kahuna servers. Both apps get an answer from the same leader.
Learn about locksWhere 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
What using it looks like
Start a node, pick storage, and claim a resource
Cluster client
- .NET
- TypeScript
using Kahuna.Client;
var client = new KahunaClient(new[]
{
"https://kahuna-1.internal:8082",
"https://kahuna-2.internal:8082",
"https://kahuna-3.internal: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)
await ProcessInvoice(2048);
import { KahunaClient } from "kahuna-client";
await using client = new KahunaClient({
endpoints: [
"https://kahuna-1.internal:8082",
"https://kahuna-2.internal:8082",
"https://kahuna-3.internal:8082"
]
});
await using jobLock = await client.acquireLock("jobs/invoice-2048", {
expiry: 30_000,
wait: 5000,
retry: 200
});
if (jobLock.acquired) {
await processInvoice(2048);
}
What this buys you
One worker owns the job. The cluster replicates the lock state, and the lease expires if the owner dies or stops renewing it.
Clients can connect through any healthy endpoint while Kahuna handles consensus, failover, and the ordered write path behind the API.
