Writing
tags
Long-form notes on backend architecture, database performance, and the parts of shipping software nobody puts on a slide.
Databases
The N+1 Query You Ship Every Sprint
featured
Nine out of ten performance regressions I have diagnosed in production were the same bug wearing different clothes: an unloaded relation inside a loop that nobody noticed because the staging database has 40 rows.
Databases
Stop Using Publish Timestamps as Ordering Keys
Sorting by published_at looks correct until two posts share a timestamp, and then pagination starts silently duplicating and dropping rows.
Frontend
Server-Driven UI Is Not a Downgrade
The reflex to reach for a SPA has a cost most teams never price in: a duplicated domain model and a second place for authorisation to be wrong.
Backend
Your Queue Retry Policy Is a Data Loss Bug
Retrying a non-idempotent job turns a transient network blip into a duplicate charge. The fix is not more retries; it is making the job safe to run twice.
Databases
Reversible Migrations Are a Team Sport
A down() method that drops the column it just created is not reversible. It is a rollback that loses data, which is worse than no rollback at all.
Databases
Indexes Are Not Free and Your Write Path Knows It
Adding an index makes one read faster and every write slower. Most teams only ever measure the first half of that trade.
Sanitising Markdown Without Shipping a Sanitiser to the Browser
Where you sanitise matters more than what you sanitise with. Render once on write, store the result, and keep the sanitiser off the hot path.
Career
The Code Review Comment I Stopped Leaving
I used to write "this could be more efficient" about fifty times a year. It never once led to a better pull request, and I eventually worked out why.
Databases
Reading Your Own Query Plans
Stop guessing which query is slow. EXPLAIN ANALYZE with BUFFERS tells you what actually happened, and the answer is usually not what you assumed.