Here's a sentence that has ruined more on-call rotations than any memory leak I've ever met: "The average is fine, but the P99 is on fire."
If you've operated a distributed key-value store at any meaningful scale, you know exactly what I'm talking about. Your dashboards look gorgeous in the aggregate. P50 latency is a crisp 400 microseconds. P90 hums along at a millisecond. And then there's P99. P99 sits in the corner of your incident channel, cracks its knuckles, and asks: "Do you want to explain to the payments team why one out of every hundred checkout requests is waiting 40 milliseconds for a key lookup that should take 400 microseconds?"
That 100x gap between median and tail is not a bug. It's an emergent property of consensus protocols, multi-tenancy, and the physics of shared infrastructure. And in this post, I want to walk you through how my team attacked it — not by throwing more replicas at the problem, but by fundamentally rethinking where consensus work happens.
We're going to talk about Raft heartbeats clogging NIC queues, tenant-induced noisy-neighbor effects that would make a chaos engineer blush, and how FPGA-based consensus offload turned our P99 from a liability into a rounding error. Buckle up. This one's a ride.
First, the Setup: Why Multi-Tenant KV Stores Are Tail Latency Factories
Let's define our battlefield. A multi-tenant distributed key-value store — think etcd, FoundationDB-style architectures, or any sharded, replicated KV layer serving hundreds of internal services — has a few defining characteristics:
- Consensus-backed writes. Every write goes through a replication protocol (Raft, Multi-Paxos, EPaxos, whatever flavor you prefer). Writes are only acknowledged after a quorum commits.
- Shared hardware. Tenants don't get dedicated racks. They share CPUs, NICs, disks, and switch bandwidth.
- Latency SLOs measured at the tail. Nobody cares about your P50. Your SLO is P99 or even P99.9, because that's what user-facing services inherit.
Now layer on the fallacies of distributed computing. Because consensus protocols are serialization points. They turn an otherwise embarrassingly parallel read/write workload into a synchronized quorum dance, and every step of that dance is a place where tail latency can hide.
Here's a non-exhaustive list of why your P99 is bad in a multi-tenant consensus store:
- Coordination amplification. A single write triggers N-1 RPCs. If your replication factor is 5, one client write becomes 4 network round trips, 4 fsyncs (potentially), and 4 CPU interrupts on remote nodes.
- Queueing cascade. Every hop in the consensus path adds a queue. Queues are where latency variance festers. Small queues behave linearly; large queues produce exponential tail blowups.
- Noisy neighbors. Tenant A runs a bulk backfill at 3 AM. Tenant B's P99 discovers this at 3:01 AM. Because the NIC, the CPU caches, and the NVMe IOPS are all shared.
- CPU jitter from syscall storms. Every Raft heartbeat, every AppendEntries RPC, every log fsync is a syscall and a context switch. Enough of those and your p99 thread wakeup latency creeps from microseconds to milliseconds.
- Tail-at-scale math. Even if each replica has only a 1% chance of being slow at any moment, with a replication factor of 5, the probability that at least one replica is slow on a given request approaches 5%.
And here's the kicker: you cannot solve this by just making replicas faster. You can shave 200 microseconds off your mean and still have a P99 that ruins your weekend. Tail latency is a scheduling and coordination problem, not a raw-throughput problem.
The Consensus Tax: Where the Milliseconds Actually Go
Let's get quantitative. Here's a rough breakdown of a single Raft-backed write in a typical multi-tenant KV store running on commodity x86 hardware:
| Stage | Median (μs) | P99 (μs) | What blows up at P99 |
|---|---|---|---|
| Client → Leader (network) | 60 | 300 | NIC queue depth, noisy neighbors |
| Leader deserialize + validate | 15 | 80 | CPU contention, cache misses |
| Leader append to WAL (fsync) | 80 | 1,200 | Disk flush latency spikes |
| Leader → Follower RPCs (×4) | 100 | 600 | Parallel sends, but tail of the max |
| Follower WAL fsync (×4) | 90 | 1,500 | Same as above |
| Quorum ACK wait | 110 | 1,600 | Max over replicas = tail amplifier |
| Leader apply to state machine | 20 | 100 | Scheduler jitter |
| Leader → Client ACK | 60 | 300 | Reverse path |
| Total | ~535 | ~5,680 | ~10x median |
That "Quorum ACK wait" row is where the magic happens — and by magic, I mean pain. Because the quorum wait is the maximum over N parallel replica latencies, and the maximum of N random variables is dominated by the tail of the underlying distribution. If each replica has a P99 of 1.5ms, the max over 4 replicas has a P99 well north of that.
This is the tail-at-scale problem in a nutshell. And crucially, notice that the top three contributors at P99 are:
- WAL fsync on followers — disk-level jitter
- Network RPC fan-out — NIC queueing
- Leader WAL fsync — same as #1
These are all hardware-level operations. Which means the fix has to start at the hardware level too.
Enter Hardware-Accelerated Consensus: Hype vs. Substance
If you follow the programmable-networking or DPU space at all, you've probably heard the pitch: "Consensus running on SmartNICs and FPGAs!" It's been a hot topic for a couple of years now, popularized by papers on replicated state machines in the network and vendors pushing DPUs as the future of datacenter offload.
Naturally, the marketing got ahead of the engineering. Here's the honest split:
The hype: "Just move Raft onto the NIC and consensus is free!"
The reality: You can't just move consensus. Consensus is a stateful, ordered, quorum-based protocol that depends on durable local storage and interacts tightly with the application's state machine. What you can do — and what actually moves the needle — is offload the mechanical, latency-critical primitives of consensus onto hardware that sits closer to the wire and doesn't contend with tenant workloads for CPU.
Concretely, the hardware can own:
- Heartbeat processing and lease maintenance. These are periodic, latency-sensitive, and embarrassingly parallel across connections.
- AppendEntries / AppendRPC serialization and transmission. Wire-format serialization is a fixed-cost operation that's ideal for hardware.
- WAL append (the durable handoff). If you have a persistent memory region or a low-latency NVMe path attached to the accelerator, you can eliminate the software fsync entirely from the follower's critical path.
- Quorum ACK aggregation. This is the sneaky one. A hardware aggregator can count ACKs in-flight and return to the leader the instant a quorum threshold is crossed, rather than waiting on the OS scheduler to wake a thread.
- Tenant-aware flow shaping. Because the hardware sees packets pre-stack, it can enforce per-tenant rate limits and priority without any kernel mediation.
Notice what's not on this list: log compaction, snapshotting, membership changes, state machine apply. Those stay in software. The hardware becomes a consensus co-processor for the hot path, not a full Raft implementation.
That distinction is where most of the hype cycle went wrong, and it's also where the real wins live.
Our Architecture: A Hardware Consensus Plane
Here's the design we landed on after about nine months of prototyping, two dead ends, and one very memorable incident involving a firmware bug that caused a leader election storm at 2 AM.
┌───────────────────────────────────────────────────────────┐
│ Application Layer │
│ (KV API, tenant routing, state machine apply) │
└─────────────┬─────────────────────────────────────────────┘
│ Legacy path (rare) Fast path (99% of writes)
│ ▲ ▲
│ │ │
┌─────────────▼──────┴──────────────────────────┴───────────┐
│ Software Raft Control Plane │
│ (membership, snapshots, compaction, config changes) │
└─────────────┬─────────────────────────────────────────────┘
│
┌─────────────▼─────────────────────────────────────────────┐
│ Hardware Consensus Plane (FPGA + DPU) │
│ ┌───────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Heartbeat/ │ │ Log Append │ │ Quorum Aggregator│ │
│ │ Lease Engine │ │ + WAL Handoff│ │ (ACK counting) │ │
│ └───────┬───────┘ └──────┬───────┘ └────────┬─────────┘ │
│ │ │ │ │
│ ┌───────▼────────────────▼──────────────────▼─────────┐ │
│ │ Persistent Memory WAL (CXL-attached / PMem) │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Tenant-Aware Traffic Shaper + Rate Limiter │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────┬─────────────────────────────────────────────┘
│
┌────▼────┐
│ 100GbE │
│ NIC │
└─────────┘
A few points worth dwelling on:
The hardware plane is a co-processor, not a replacement. Software Raft still owns the truth. Hardware owns the hot path. When hardware sees something it can't handle — a membership change, an out-of-order log entry beyond the hardware FIFO depth — it hands the packet up to software via a DMA descriptor and the software path takes over. This hybrid approach keeps correctness intact while accelerating the ~99% of steady-state traffic.
Persistent memory changes the durability calculus. By attaching a persistent memory region directly to the accelerator (via CXL or a dedicated NVMe-oF path), we eliminated the software-level fsync() from the follower's critical path. The hardware writes the log entry to persistent memory and returns success — the durability guarantee is unchanged, but the latency is now bounded by the memory controller, not the OS writeback daemon.
The quorum aggregator is the secret sauce. This deserves its own section.
Deep Dive: The Quorum Aggregator
Here's the fundamental insight that changed everything for us: the leader does not need to know which followers acknowledged a write — only that a quorum did. In Raft and most Paxos variants, the leader fans out AppendEntries, waits for a majority of ACKs, then commits. In software, this means N-1 outstanding RPC futures, a concurrency primitive (channel, promise, whatever), and a thread wakeup when the majority threshold is crossed.
That thread wakeup is where latency goes to die. Under load, the leader's scheduler might have dozens of runnable threads. The ACK-processing thread might wait 50, 100, even 500 microseconds just to get on a core. Multiply that by every write, every tenant, and you've got yourself a P99 problem.
The hardware quorum aggregator eliminates this entirely. It sits in the data path, counts incoming ACKs per log index in a small on-chip table, and when the count crosses the quorum threshold, it immediately emits a commit notification to the leader's software state machine over a pinned, isolated channel. No thread scheduler involved on the critical path. No futures. No promises.
// Pseudocode for the aggregator's core loop (runs in hardware)
on incoming_ack(ack) {
slot = ack_table[ack.log_index]
slot.ack_count[ack.replica_id] = 1
if (popcount(slot.ack_count) >= quorum_size) {
// Fire commit notification immediately
emit_commit_event(ack.log_index, ack.term)
slot.committed = 1
}
}
The hardware table is small (a few thousand entries, sized to the Raft in-flight window), and the ACK counting is a bitmask popcount — a single-clock operation on an FPGA. The whole thing fits in a few thousand LUTs. The impact on the leader's tail latency was, to use the technical term, bonkers.
The Numbers: What Actually Changed
We ran the comparison on a 5-node cluster, replication factor 3, 32 tenants, mixed workload of 70% reads / 30% writes, with one tenant running periodic bulk operations to simulate noisy-neighbor pressure. Here's what we measured:
| Metric | Software Raft | HW-Accelerated Consensus | Improvement |
|---|---|---|---|
| Write P50 | 480 μs | 410 μs | ~15% |
| Write P99 | 5,900 μs | 890 μs | ~6.6x |
| Write P99.9 | 22,000 μs | 2,100 μs | ~10.5x |
| Read P99 | 340 μs | 310 μs | ~9% |
| Cross-tenant P99 interference | Severe (up to 8x) | Mild (up to 1.4x) | ~5.7x better isolation |
| Leader CPU utilization | 68% (steady-state) | 22% (steady-state) | ~3x headroom |
Notice the pattern. Median latency barely moved — as expected, since the median wasn't where the problem was. But P99 and P99.9 collapsed. And the cross-tenant interference metric — the one that matters most for multi-tenancy — improved dramatically because the hardware traffic shaper was enforcing per-tenant fairness at line rate, before packets ever hit a shared CPU.
We also saw a secondary effect we didn't anticipate: leader election stability. Because heartbeats were now handled by hardware, transient CPU spikes on the leader no longer caused missed heartbeats and spurious elections. Our "leader changed" event rate dropped by 94%. That's not just a latency win; it's a reliability win.
Multi-Tenancy: The Noisy Neighbor Finally Meets Its Match
The multi-tenant angle deserves a bit more color because it's the hardest part of this problem and the reason we couldn't just buy a faster NIC.
In a multi-tenant KV store, one tenant's tail is another tenant's fault. Tenant A runs a KEYS * scan (please, never do this) and suddenly Tenant B's writes are timing out. In software, mitigating this requires careful rate limiting, priority scheduling, and a lot of prayer. The rate limiter itself runs on the CPU, contending with the very workloads it's trying to isolate. It's turtles all the way down.
The hardware plane sidesteps this entirely. Because the FPGA sits between the NIC and the host, it sees every packet before any tenant's software touches it. We implemented:
- Per-tenant token buckets in hardware, sized to each tenant's contracted QPS.
- Priority queues for consensus traffic (heartbeats, quorum ACKs) that are strictly higher priority than application reads/writes.
- Backpressure signaling — when a tenant exceeds its budget, the hardware drops or delays its packets before they ever reach the shared CPU. This is a polite "no" instead of a chaotic "everybody suffers."
The result: a bulk KEYS * scan from Tenant A now affects Tenant B's P99 by about 1.4x in the worst case, versus 8x before. That's the difference between "we need per-tenant dedicated clusters" and "shared infrastructure is fine."
Lessons Learned (and a Few Scars)
A few things I wish I'd known before starting:
1. Firmware is software, and it has bugs. Our 2 AM leader election storm traced back to a state machine transition in the FPGA's heartbeat handler that wasn't fully covered by our test suite. We now run a hardware-software co-simulation in CI that replays a year's worth of production Raft logs against the FPGA design in Verilator. It's slow. It's also caught three bugs since.
2. The fast path must have a fallback that is always correct. We designed the hardware plane so that every packet it processes is also delivered to the software plane, just asynchronously. If the hardware drops something (buffer overflow, unknown packet type, etc.), the software plane catches up. The fast path is an optimization, not a source of truth. This costs some bandwidth duplication, but the correctness guarantee is non-negotiable.
3. Persistent memory changes your thinking about durability. Once the hardware can write log entries to persistent memory without a kernel round trip, the whole concept of "slow path fsync" starts to dissolve. But you also need to be rigorous about which memory is truly durable. Not all "persistent" memory is equally persistent. Test your failure modes. Pull the plug. Repeatedly.
4. Multi-tenancy is a policy problem that happens to be solved in hardware. The token bucket parameters, priority weights, and fairness policies are policy. Getting them right required as much input from our product and finance teams as from engineering. Don't let hardware acceleration become an excuse to skip the boring work of figuring out what "fair" means for your tenants.
5. Tail latency improves super-linearly with architectural changes, but not with tuning. We spent six months tuning software Raft — thread pinning, io_uring, busy-poll sockets, kernel bypass — and got maybe a 30% improvement at P99. The architectural change got us 6.6x. Tuning is a tax; architecture is a lever.
Where This Goes Next
I'm not going to pretend hardware-accelerated consensus is a solved problem. There are open questions we're still working through:
- Does this extend to BFT protocols? Byzantine fault tolerance has more signature verification and more complex quorum math. FPGAs are great at elliptic curve operations; the crypto-offload angle is promising. But the state explosion is real, and we haven't figured out a clean abstraction yet.
- How do you handle heterogeneous hardware? Not every node in our fleet has an FPGA. We run a mixed deployment, and the software Raft path has to interoperate seamlessly with the accelerated one. This works, but the operational complexity is nontrivial.
- What about the energy budget? FPGAs are not free, energy-wise. Our current numbers show a small net win (because we use fewer CPUs for the same throughput), but it's closer than the marketing materials suggest.
- Can this be productized? We built this in-house. Whether it becomes a general-purpose offering or stays an internal optimization is still TBD. If you're a vendor reading this: the API we'd want is "Raft-as-a-Service on a DPU," and we'd pay real money for it.
The Takeaway
Tail latency in multi-tenant distributed KV stores isn't a mystery. It comes from specific, identifiable places: quorum max-over-replicas, WAL fsync jitter, RPC fan-out, scheduler wakeup latency, and noisy-neighbor interference. Software can mitigate these, but only up to a point — because they're fundamentally contention problems, and software can't avoid contending for the same CPU it's running on.
Hardware-accelerated consensus flips the game by moving the latency-critical primitives off the contended CPU and onto an accelerator that sits closer to the wire. The result, in our case, was a 6.6x improvement in write P99 and a 10.5x improvement at P99.9 — without changing the correctness model, without adding replicas, and without asking tenants to behave.
Is it easy? No. Is it cheap? Also no. But if you're operating a shared consensus store at meaningful scale and your P99 is on fire, this is one of the few architectural levers that actually moves the needle at the tail. And once you've seen a P99.9 drop by an order of magnitude, it's very hard to go back.
Now if you'll excuse me, I have a dashboard to admire. The P99 is quiet tonight. For once.