What is Ticketing?
Ticketing is a dedicated lock server designed for exactly one job — distributed locking. It's a single Rust server binary paired with official per-language clients that all implement the same binary protocol, byte for byte. Just two operations — acquire and release — a per-key FIFO queue, fencing tokens, and an optional Raft cluster you turn on when you need it. Everything a distributed lock needs, and nothing else.
How is this different from locks built on a store?
Most distributed locks in production lean on a key-value store — a Lua script or Redlock on top of Redis, or a lock built on ZooKeeper's or etcd's sessions and leases. Redis is a great store, but it's a key-value store repurposed for distributed locking, not a purpose-built lock system, and that shows up as structural overhead: the parsing cost of a general-purpose protocol, and the overhead of general-purpose data structures, both come along for the ride.
Ticketing was designed exclusively for distributed locking from day one, so every layer is built around locks.
- Protocol — fixed-width binary fields, not text and not a general-purpose serialization format. Values are read straight off byte offsets with no parsing, and pipelining lets you send the next request without waiting for the previous response.
- Server internals — the entire state is a per-key FIFO queue plus a lease timer. The request path doesn't even allocate on the heap.
- Operations — start one server binary (or container), configure it with a handful of environment variables, and you're done. No schema design, no separate store, no operational knowledge unrelated to locking required.
Performance
- Handles over 1 million ops/sec while using under 10MB of memory
Why Ticketing
🚦 Ordering integrity — FIFO queue with direct handoff
First come, first served. When the holder releases, the lock is handed directly to the front of the queue with no re-contention. No starvation from polling-and-retry lock contention, and no retry storms.
🛟 A dead client doesn't leave the lock stuck — lease
If the process holding the lock dies or its connection drops, the server automatically reclaims the lock once the lease duration set at acquire time elapses, and hands it to the next waiter. Forgetting to release doesn't bring the whole system to a halt.
🔑 Preventing out-of-order work — fencing tokens
There's one failure a lock alone can't prevent: a holder that wakes up late — unaware its lease already expired — and asks to finish its work anyway. Ticketing issues a monotonically increasing fencing token with every acquire. As long as the protected resource enforces a single rule — "reject any token lower than the last one seen" — even this last gap is closed. See How It Works for the full explanation.
🗳️ A non-stop cluster built on Raft
A single server is enough on its own, but when you need zero downtime, form a cluster of 3 (or 5) nodes. Every lock state change is only finalized after a majority of nodes agree via Raft consensus, so the same lock is never issued twice at once even if the leader dies or the network partitions. If the leader fails, a new one is elected in roughly a second and clients switch over automatically. Service keeps running even as nodes go down one at a time — say, during cloud instance reboots or a rolling maintenance pass.
🔒 Built-in auth and TLS
Every connection goes through challenge-response token authentication immediately after connecting, and the token is never sent over the wire in plaintext. Encrypt the whole connection with TLS whenever you need to.
🌐 The same protocol, byte for byte, across every major language
Rust, Java/Kotlin, JavaScript/TypeScript, Python, C#, Go, Ruby, C/C++ — every official client implements the same binary protocol, with an API that feels natural to each language's ecosystem (async or blocking). A lock acquired from any language queues fairly with clients written in any other. See Libraries for install instructions and examples.
Just two operations
True to a lock-only server, the surface area is minimal too.
- Attach a key to the resource you want to protect — e.g.
order-1234,account-77,daily-batch. - Acquire that key before doing the work — if someone else holds it, you wait your turn in the FIFO queue.
- Release it when the work is done — the next waiter takes over immediately with no re-contention.
The only options on top of these two operations are lease (automatic reclaim) and waitTimeout (give up waiting) — that's the entire API.
What to read next
- How locks are actually assigned and how the cluster stays up — How It Works
- The exact byte-level spec of what crosses the wire — Protocol (API)
- Generate the server run command — Ticketing Server Deployment