Long-form notes on software, distributed systems, and the craft of building.
One post, every Monday. Search or browse the archive below.
Database per Service Is Free Now. That Is Not a Reason to Use It
A free tier that doubles changes the inputs to a decision, not the decision. In week one I predicted Bullpen would split prices and history into two services with two databases. Then Neon made database per service look free, and I had to decide whether that changed anything. This is the decision history: five data and deployment decisions, each with its conditions, the options I weighed, why one won, and what would make me reverse it.
Architecture as Code Has Three Jobs: Describe, Govern, Remember
In Bullpen's first week, the planned architecture model still named a stock provider I had turned down, and a footer change and a test followed it. Nothing failed. I use that incident and two others to argue that architecture as code has three jobs: describe the system, govern it, and remember why it looks the way it does. Then I follow the first real change after the fixes, product analytics, through all three: a decision record before the model could name it, built and planned architecture that disagreed, and a rule that composes the two instead of editing either.
When to Use Microservices in 2026: Scaling Alone Is No Longer the Reason
On the day the Dow posted a then-record gain, Robinhood's customers could not trade from the open to the close. Splitting out the hot part so it scales alone was the old answer; a serverless platform now does that per function. I open this series with Bullpen, a paper-trading league on live market data, and argue when to use microservices in 2026: only for a reason I can name, with a check, a measurement or a bill behind it.
Stamp vs Control Coupling: Where Does the Write Decision Live?
Control coupling and stamp coupling sit side by side in the Constantine taxonomy, ranked worse than data coupling and not much else. When I re-read it with a real Kotlin applyDiscount refactor in front of me, the ranking was not the interesting part. The question it does not answer is where the write decision actually lives.
Your Queue Won't Drain: The Arithmetic of Backlog Recovery
A healthy-looking consumer fleet can sit on a 3-million-message backlog that never shrinks. These are my notes on the arithmetic behind it: surplus = capacity − arrival, drain = backlog ÷ surplus, and why a fleet sized for steady-state has zero recovery capacity. I built a small TypeScript simulator to watch retry amplification park a correctly sized fleet in a metastable failure, and worked out when shedding beats draining.
Backpressure Is a Contract Every Caller Must Honor, Not a Setting
A bounded queue in one service does nothing if the caller above it keeps pushing. These are my notes on backpressure as an end-to-end contract: what the callee owes, what every caller owes back, and why the Azure OpenAI retry-amplification incident is what a broken clause looks like at hyperscale.
The Bug That Wouldn't Compile: Porting a Reordering Mistake to Hydro
I planted an arrival-order bug in a hand-rolled Rust fan-in aggregation, reproduced a 51% undercount with a seeded shuffle, then ported the same logic to Hydro 0.17-alpha. The unordered merge refused to compile my non-commutative fold — these are my notes on what that guarantee is, what manual_proof! only attests, and when the seam costs are worth paying.
Architecture as Code with Structurizr DSL: A C4 Workspace Both a Reviewer and an Agent Can Read
I committed a Structurizr DSL workspace next to a Kotlin/Spring billing service and wired ArchUnit into Gradle so CI fails the moment the code drifts from the C4 design. Here is the workspace.dsl, the test that backs it, and what changed when a coding agent could read both files instead of guessing from packages.
Engineering Before Inference: The Question Zero Token Architecture Is Actually Asking
Lately I keep hearing a sentence that would have been absurd three years ago: "I can't do it now — I ran out of tokens." These are my notes from digging into Zero Token Architecture — the idea Kelsey Hightower took from a throwaway post to a PlatformCon keynote — and the principle I want to build on it: every AI call is an architectural decision, and the costs that matter most were never the tokens.
When SQL Is Enough for Streaming: What Incremental View Maintenance Guarantees — and What It Refuses
The 2026 pitch is that a hand-written stream job collapses into one CREATE MATERIALIZED VIEW, so I built one in RisingWave and spent my study time trying to break it. These are my notes on the consistency the view actually delivers as events arrive, why every join in it is a standing memory bill, and the queries that refuse to be incremental — with a Node consumer riding the view's changefeed over the plain Postgres protocol.