All posts
Long-form notes on software, distributed systems, and the craft of building. Shipping one a week.
Convergence Is a Property of Your Merge Function, Not the Network
I once watched an afternoon of offline edits vanish under a last-writer-wins sync, and the fix was not better networking — it was a better merge function. These are my notes on why CRDT replicas converge: a merge that is commutative, associative, and idempotent. I rebuild a minimal add-wins OR-Set in TypeScript, run it, and weigh what the guarantee costs in tombstones and memory.
Kotlin 2.4: The Three Changes That Moved My Hand on the Keyboard
Kotlin 2.4.0 shipped a long changelog, but only three features changed how I actually type: stable context parameters, explicit backing fields, and (still behind a flag) name-based destructuring. Here is my backend-engineer's cut, verified against the 2.4.0 compiler, plus the K1 removal I had to put on a calendar.
Catching a Retry Race with One Seed: Deterministic Simulation in Rust using turmoil
I had three flaky retry tests no one could reproduce on a laptop. I rewrote one in Rust on top of turmoil, Tokio's deterministic simulator, and a single 8-byte seed pinned the partition race byte-for-byte. These are my notes on what the seed actually controls, what leaks past it, and when deterministic simulation testing is worth the seam.
Reading AG-UI as a wire protocol, not a framework
I kept rebuilding the same SSE envelope every time I wrote an agent UI. AG-UI is the first serious attempt I have seen at standardising that envelope. In this post I strip the protocol down to its wire shape and rebuild a minimal Spring WebFlux endpoint that speaks it without an SDK.
Two-Phase Commit on the JVM: The Blocking Problem Nobody Puts in the Diagram
I crashed a Two-Phase Commit coordinator on purpose in a small Kotlin simulation to measure how long participants stay locked when the coordinator vanishes between phases. The result is the part of 2PC the diagrams never show — and the reason I would model most cross-service writes as a saga instead.
Drop the Right Requests First: Priority-Aware Load Shedding Under Overload
Static RPS caps shed the wrong traffic. Concurrency is what saturates a service, not request rate. From my notes after reading the InfoQ piece on overload protection, Uber's January writeup on Cinnamon, and Netflix's QCon SF talk on service-level prioritized load shedding, here is why latency is the right control signal — and how a small priority taxonomy plus an adaptive concurrency limit keep the cheapest traffic shedding first.
Actor-per-Entity vs Postgres Optimistic Locking: A Seat-Reservation Bake-off
I ran the same hot-key seat reservation workload two ways: Postgres with a version column and retries, and a single actor per seat. The actor design did not scale better — it moved the hard problem from concurrency control to routing and rebalance correctness, and that trade was the easier one to reason about under hot keys.
Auditing a Scala Service Against Chad Fowler's Four Regenerative Constraints
I walked a Scala order-processing service from my notes through Chad Fowler's four regenerative constraints. Two passed for free, two would force a real redesign. Here is what I learned about where "loosely coupled module" ends and "regenerative component" begins, and which parts of the redesign I would actually pay for.
Preregistering Experiment #1: How Fragile Are Production JSON Extraction Prompts?
The first concrete experiment in the precision research line — committed in public before the data is collected. Five perturbation classes, fifteen variants, four metrics, four falsifiable hypotheses, and a runnable companion repo with tests.
Durable Execution Isn't About Agents — It's About Replayable Backend Workflows
I came to durable-execution runtimes through the agent press, but the constraint that surprises everyone is determinism on replay. These are my notes from working a six-step payment reconciliation as a Restate workflow in TypeScript — the line that broke replay, the mental model that fixed it, and the trade-offs that come with the pattern.