126 entries
The dev log
Bugs I hit and patterns I kept, dated and searchable, straight from the notebook I keep while building.
How it failed
12 / 126 entries
Start here
A kiosk isn't a user
Authenticating physical hardware — a kiosk, a counter, a wall display — as its own identity class, because the threat model for unattended hardware is genuinely different.
backendHealing stuck state on every boot
A process that dies mid-workflow leaves something half-finished, and nothing transitions it — because the thing that would have just stopped existing. Run a recovery pass on every startup.
devopsNine Dockerfiles, and getting back to two
No single bad decision — just a dozen individually reasonable ones compounding. How the Docker setup sprawled, and the rule I took from consolidating it.
backendOffline sync that's actually safe to replay
Queuing actions offline is the easy half. Replaying them without duplicating work or corrupting state is the half that needs two layers of idempotency.
backendpgBouncer, and the search_path bug that corrupted data
Connection pooling becomes necessary at scale — and transaction pooling has one sharp edge that silently wrote to the wrong schema.
securityRevoking a token that's stateless by design
JWTs can't be taken back once issued. Here's the gap that caused, and the one-column fix I now build on day one.
securityRow-level multi-tenancy, and the one bug that matters
One schema, a tenant_id on every table, isolation enforced entirely in application logic. Simple to operate, and exactly as strong as the discipline of every single query.
backendThe transactional outbox
The dual-write problem, and the pattern I now reach for on every project so a side effect can't silently vanish.
backendWhat a client missed while it was gone
Raw Socket.io tells you a client reconnected. It doesn't tell you whether it's caught up — and for an unattended screen, a silent gap is the whole problem.
devopsWhat a load test actually tells you
The measurement mistakes that quietly invalidate a result, and what 'the numbers got worse under more load' turned out to mean.
How they failed
Filed by failure mode rather than by which part of the stack broke, because that's the part that carried between projects. 15 of 73 land in one bucket: it could not have worked.
It could not have worked
15A race, an ordering, one column holding two things. The shape ruled it out before the code ran.
It said it worked
13Green, 200, saved, “already handled” — and wrong. No error anywhere to go on.
Two copies drifted
13One idea kept by hand in two places — schema and migration, dev and prod, app and app.
The safety net had a hole
13The test, the audit log, the scanner, the CI run — covering less than I assumed it did.
Only visible by using it
11Invisible to a code read. Found by being the real user, on a real device, at a real width.
Built, and nothing used it
8Shipped, typechecked, dependency-injected, unreachable. Nothing ever called it.
Where the bugs live
Two thirds of them sit outside the application logic — in infrastructure, data integrity, or the auth layer.
73 total
Notes by area
53 total
When they were found