Writing · 19

Notes.

Write-ups on real problems from client work and my own, kept specific rather than general.

How I work

Decisions, principles, and the reasoning behind them.

Null, never zero

A missing figure is obvious and a zero isn't, so bad input has to be refused the same way by every implementation that reads it.

invariantscurrencycross-platformSep 2026

Guards have to be synchronous

A busy state greys the button out, but it doesn't stop a second submit. The gate has to flip a plain variable in the same tick as the first call, and the call sites matter more than the component.

reactconcurrencyformsSep 2026

One document, three destinations

A contact form that produces a real project brief (on screen, as a PDF and as a stored record) built so the three can never disagree about what it says.

architecturesingle source of truthpdfSep 2026

Why the PDF renderer isn't a browser

The contact form on this site produces a branded PDF. The obvious way to render one is HTML plus headless Chromium, and I decided against it. Here's what each approach costs.

pdfserverlessbuild decisionsSep 2026

Two implementations, one dataset, on purpose

The same money rules written twice, in two languages, and both held to a committed corpus of answers that neither of them owns.

architecturetestingcorrectnessAug 2026

Why I stopped building automations

I spent years on no-code and low-code automation work, and it taught me how to design systems. In the end the tools couldn't hold what I'd learned.

careersystems designautomationAug 2026
2 more

What automated review is good at, and what it isn't

Twenty-five code reviews and a whole-branch pass stayed green on a branch with two real problems. The pattern in which modules held them is a better guide to where test effort belongs than any coverage number.

testingcode reviewstate machinesJul 2026

A ledger that cannot pay twice

Metered credits across three balance buckets, built so a duplicated payment event, a lapsed subscription or a client with bad intentions can't change a balance wrongly.

postgresbillingidempotencyJun 2026

Deep dives

Specific problems, in detail.

Designing around a source that publishes on a schedule

A fallback built for permanent gaps will also hide temporary ones, which is why a system waiting on a scheduled source needs two lists rather than a better fallback.

syncapi designtimeSep 2026

The number that told Postgres it was on a spinning disk

A managed Postgres host ships a cost setting that describes a mechanical disk. Correcting it let the planner pick a 232MB index over a 4GB table, and shrank the cold working set enough that the count stopped going cold.

postgresquery planningindexesSep 2026

Why work_mem changes the algorithm, not just the speed

Below a threshold Postgres doesn't just run a hash join slower, it stops choosing the hash join. Three findings from tuning anti-joins against a very large suppression list, none of which produced an error.

postgresquery planningstatisticsSep 2026

A road network that only worked on rectangles

Replacing a global construction with one that only ever relies on two neighbours at a time, built so the well-behaved case provably reduces to the old output, and one measured trade-off I took anyway.

geometryinvariantstrade-offsAug 2026

Testing against the thing that actually loads your file

A round-trip test proves an encoder agrees with its own parser. Asking Win32 to load the output proves something else entirely, and it turned an undocumented format limit into a measured number.

testingwindowsfile formatsAug 2026

Eighteen seconds to seven hundred milliseconds, and the test that proved nothing changed

A geometry sweep went from about eighteen seconds to seven hundred milliseconds. The part worth keeping is the optional parameter and the equivalence test that turn 'nothing else changed' into something you can run.

performanceprofilingcorrectnessJul 2026
5 more

Making a slow count fast without making it wrong

Cutting a filtered record count from 88 seconds to 3.4 by moving it into SQL, and why the whitelist that made it safe mattered more than the speed.

postgresperformancecorrectnessJul 2026

The column the cascade forgot to clear

A denormalised column that points at a catalogue, and not at a parent row, survives the cascade. That's what turned a lost link into one I could recover.

postgresdata recoveryrlsJun 2026

Two devices, one todo list, and a tiebreak that wasn't

How a locally assigned row id broke deterministic replay across two devices, and why I fixed it with a committed corpus as well as a smarter tiebreak.

event sourcingtestingsyncJun 2026

A similarity threshold borrowed from the wrong comparison

Query-to-chunk and chunk-to-chunk cosine similarity aren't on the same scale, so a threshold calibrated on one filters out everything measured by the other.

retrievalembeddingsmeasurementMay 2026

The job that died without dying

A worker can't reliably record its own death, and whatever cleans up after it can't depend on the thing it's cleaning up after. Three independent fixes for a queue row that sat at processing for twenty-three hours.

queuesserverlessfailure modesApr 2026