A green check that never looked

Written August 2026

From building a multi-tenant business platform single-handed — one of four notes on what the work actually taught.

A root layout threw on every request. Every static check in the repository passed: the type checker, the unit suite, every lint gate, the production build. The deployment was green.

The only signal was the end-to-end runner never finding the app ready, reported fifteen minutes later as a timeout, with the cause buried in a log line repeating once a second.

Why nothing caught it

All of those checks are static. None of them renders a page in a server that answers. A tree can pass a type checker, a thousand unit tests and a production build while returning 500 to every single request, because not one of those things makes a request.

So I already had the check that should have caught it: a probe that boots the built app, requests a page, and counts the framework fibres attached in the returned markup. It had existed for months. It reported ok — 7 fibre(s) / 34 elements.

The framework’s own error page is React, and it hydrates.

The probe had been returning the HTTP status since the day it was written, and the verdict never read it. So it fetched the page, got a 500, rendered the framework's built-in error page — which is a React tree, and attaches fibres exactly like a working page — counted them, and reported success. It was not broken. It was answering a different question from the one everybody believed it was answering.

The rule I took from it

The fix is one line: fail on a status of 400 or more. The lesson is not the line. It is that a green check is not the same as a check that looked, and the moment to find out is when a check passes on something you fully expected it to catch. That is the cheapest signal you will ever get that an instrument is pointed at the wrong thing, and it arrives disguised as good news.

I now treat "it passed" as a claim that itself needs evidence, in exactly one situation: when I have deliberately broken something to watch a check catch it, and it does not. Every gate I have written since is shown red against the defect it exists for, before it is allowed to be green.

The corollary is a habit rather than a tool. Any change touching a layout, a provider, or anything else that every route renders gets one manual step before I believe the pipeline: build it, start it, request a page, read the status code.

What this is from

These come from one project: a multi-tenant business platform for professional firms, where the customers, the projects, the hours, the quotes and the invoices are joined end to end instead of sold as five tools that happen to share a login. Around it sit the public sites, the documentation and the developer tooling it is built with — seven deployed applications and one Postgres database, in a single repository.

It is built and run by one person, outside the hours of a full-time job. That is context rather than a boast, and it is the reason the notes read the way they do: alone, you cannot out-work a mistake, so what matters is leverage — what to automate, what to refuse to claim, and which checks earn back more than the time they cost.

The code is private and none of it is given away here. What these describe is method: how something was measured, what the measurement contradicted, and what changed as a result. A method is worth more read than hoarded — and it is the part nobody can copy without first understanding it.