Skip to content
How it worksVerificationAgentsBenchmarkBlogBlogReleasesReleasesStar

Deterministic replay and fix verification for journal-driven services.

Product

How it worksFix verificationFor coding agentsAgent benchmarkPerformanceRelease notes

Developers

SourceAgent skillsJournal formatAgent guidellms.txtContributing

Blog

All postsGuidesConceptsProductEngineeringRSS

Project

LicenseDCOReport a bugContact

Install Kavach CLI & Agent Skills

curl -fsSL https://www.thekavachlabs.com/install.sh | shnpx skills add kavachlabs/kavach
© 2026 Kavach LabsPre-alpha. Apache 2.0.
kavach
Blog/Engineering/Deterministic Verification

81.2 Nanoseconds: Designing an Always-On Production Flight Recorder

This post is about where the determinism boundary should live in a backend service, and how our shared-memory ring buffer records every event in 81.2 nanoseconds.

KC

Koustav Chowdhury

FounderOctober 14, 20264 min read

Before I introduce our flight recorder, let me tell you who I am and where this started. I have worked in financial industry for about half-a-decade, and when I recently build HFT infrastructure from scratch, we had to record live traffic without slowing down the hot path. While building that, I found certain patterns that are helpful for me, and also helpful for agents, to debug faster, to reproduce the issue exactly, and to verify the fixes.

Flight recording12 is about journaling the inputs which cause transitions in your service handler. What is a determinism boundary, you may ask? A determinism boundary is a software's internal line which determines what events get captured for offline replay.

Why does a lightweight boundary help to debug a bug faster? Whenever we are stuck reproducing what might have happened by looking at the logs, the network packets, or different containers, a simple handler boundary lays out in bare bones the events that took place, which caused the software to end up in the state that it did. Let's say you have a bank account. Your bank account is a summation of all the credits and debits of your money. Now imagine one day you go up to your bank, and it says that you have 10 dollars. When you checked last night, you had 100k. So you will demand the transaction ledger for this, right? You are not ready to accept a guess from a test lab when your live balance is wrong.

Where should the determinism boundary live? The top lane shows a Full-VM Hypervisor Boundary using x86 instruction-retired PMC and a Guest OS pinned to 1 core per VM, passing through a Container Topology of Broker, DB, and Mocks, where adding a printf causes a Timing Butterfly Effect with no local ARM64 support. The bottom lane shows the Kavach Handler Boundary (SPEC.md §10.7) where a Service Handler Step reads env.Now(), env.Read(), and env.Emit() across an 8 MiB Shared Ring at 81.2 ns per event with 0 syscalls, drained by kavach-recorder into a 1,954-byte .kavach fixture that replays in 61.1 microseconds.
Determinizing at the handler environment boundary avoids the x86 instruction-counter butterfly effect

An in-process flight recorder is kind of like that. It has a transactional ledger which keeps account of all the state changes, all the state mutations that lead up to the crash. In a way, it makes the execution of an application auditable on every step.

Now, since I have worked in the finance industry, I see its applications everywhere. It helps to reproduce bugs, to actually see what events preceded the crash happening, and so on.

Spike pitWhy syscall recording (rr) isn't free in production either

Tools like Mozilla's rr move the boundary up from the hypervisor to Linux kernel syscalls and perf counters. That works well for local C++ debugging, but ptrace traps, seccomp filters, and single-threaded serialization add 1.2x to 2x runtime overhead—far too heavy to leave running inside a live payment ledger or order gateway.

func (l *Ledger) Handle(env kavach.Env, in kavach.Input) error {
    now := env.Now()          // recorded as a 'clock' frame
    var nonce [8]byte
    _, _ = env.Read(nonce[:]) // recorded as a 'rand' frame
 
    entry, err := l.apply(in.Data, now, nonce)
    if err != nil {
        return err
    }
    env.Emit("ledger.entries", entry) // recorded as an 'output' frame
    return nil
}

Why shared memory matters for recording#

Starting from a snapshot, if you keep replaying the events that are in the journal, you should end up with the exact crash state. That's the ultimate goal for a flight recorder. What makes it challenging are certain bits of overhead sprinkled through the operating system. Overhead comes from the kernel. It can come from system calls. It can come from the fact that we are copying bytes over a pipe on every event.

Having the ability to record deterministically in shared memory in about eighty nanoseconds is one of the key guarantees of Kavach34, and that is what makes always-on recording possible in production.

go test -run '^$' -bench RecorderStep -benchtime 2s -count 5 ./replay
Deep diveWhat the 81.2 ns/event benchmark includes (and doesn't)

The benchmark runs a sustained stream that fills the 8 MiB ring within milliseconds, so the 81.2 ns/event median includes any backpressure wait for kavach-recorder to drain, number, and compress frames on another core. It injects a seeded math/rand source rather than crypto/rand so the benchmark measures Kavach's ring and framing overhead rather than the kernel's CSPRNG.

Challenges of recording live production services#

These challenges all come down to recording without slowing down the service. Production recording has several such traps.

Losing the last event on a crash. Can a flight recorder capture everything? Capture every panic? How does it know what the input was when the process died? Which step was the handler running? If these events aren't in shared memory, a crash wipes out the very input you needed to see. As a company, Kavach Labs is going to tackle these challenges so that the shared ring keeps the last input safe on disk.

Slowing down the hot path. Software often writes logs or traces in more than one place. Say you design a service that writes every step over a pipe. How do you record without paying for a system call on every event? With 1,000 requests a second it may behave fine, but under a traffic spike you are blocking the handler on the kernel.

Replaying without external services. One system requirement for fast replayability is that your handler should read its clock and inputs from the journal. Most single-threaded deterministic software follows this principle, but quite a few chunks of software still don't. How do you model those? These are the uncomfortable parts of the system that we want to tackle.

The 33-record ledger crash fixture: scrub through the recording to inspect inputs, clock reads, random reads, and outputs.

We're building Kavach Labs to tackle this problem head-on. We love deterministic recording as an architectural concept, and we want agentic software to be written and deployed so that it's easy to capture a bug, replay it, fix the code, and deploy the fix with more confidence.

References

  1. ArticleSo you think you want to write a deterministic hypervisor?antithesis.com↩
  2. ArticleFree log storage with a time machineantithesis.com↩
  3. SpecKavach Journal and Protocol Specification (v0)github.com↩
  4. CodeKavach Reproducible Benchmarksgithub.com↩
Series · Part 2 of 6

Deterministic Verification

  1. 1Event Sourcing
  2. 281.2 Nanoseconds: Designing an Always-On Production Flight Recorder
  3. 3Why Coding Agents Write Narrow Fixes (And Why Logs Won't Save Them)
  4. 4The Hidden Tests Pass. The Contract Doesn't.
  5. 5What Invariants Should My Service Have?
  6. 6How to Read a Kavach Strip Chart
← Part 1Part 3 →
  • replay
  • determinism
  • flight recorder
  • benchmarks

On this page

  1. Why shared memory matters for recording
  2. Challenges of recording live production services

Quick links

  • 1So you think you want to write a deterministic hypervisor?
  • 2Free log storage with a time machine
  • 3Kavach Journal and Protocol Specification (v0)
  • 4Kavach Reproducible Benchmarks
Ask ChatGPTAsk ClaudeStar on GitHub

Keep reading

  • Why Coding Agents Write Narrow Fixes (And Why Logs Won't Save Them)Engineering4 minOct 16, 2026
  • What Invariants Should My Service Have?Guides4 minOct 19, 2026
  • How to Read a Kavach Strip ChartGuides4 minOct 19, 2026