Four ways a system tells you it is fine

9–13 minutes
measured on my own machine

Between the middle of July and the beginning of September I found six faults across six of my own systems. A signup form, a publishing chain, a laptop under my desk, an audit machine, an agent platform, a delete button. Different languages, different machines, different years of my life.

Not one of them produced an error message. Not one showed up red on a dashboard. In every single case something told me things were fine, and in every single case that something was a thing I had built for the express purpose of telling me when they were not.

That is the part worth an afternoon of your attention. The faults themselves are ordinary and mostly cheap to fix. What they have in common is a reporting layer that was confident, sincere, and pointed slightly to the left of the truth. Laid out together they are not six stories. They are four.

Six systems grouped into four patterns, each naming the instrument that reported everything was fine
Grouped by what went wrong with the reporting, not by what went wrong with the system. The right-hand column is the one that matters: in each case, the thing that said it was fine.
Pattern one

The silent accomplice

Success reported for work that never happened

My second site had a signup form that accepted nobody for twelve days and mentioned it to no one. Somebody typed an address, pressed the button, and the page reloaded and forgot — which is exactly what a page does when nothing at all is listening. The version in my repository was correct the whole time. The publishing system rewrote a single character while saving, and a browser meeting that character refuses the entire script. Everything that read what I had written reported green, accurately, for twelve days.

The second one is worse, because it is still open. My video line renders finished video, and the tool I publish through accepts video. The chain between them is nailed to pictures in five separate places. Handed a video it drops the attachment, returns success, and marks the card as sent. Downstream, nothing disagrees: a reconciliation step books it as published after a day. Seventy-one of seventy-one published posts have carried an image. No video has ever left the house.

What makes this pattern expensive is not the missing work. It is that the report is what everything downstream trusts. One cheerful lie at the start becomes a consistent, confident, entirely wrong belief held by every part of the system at once, and every part agrees with every other part.

Pattern two

The false witness

The measurement itself is wrong

In August the ten-year-old laptop that runs every nightly job on this site froze. I restarted it, looked at the memory figures, and reported that there was no memory problem at all: plenty free, and the counter that indicates real pressure had not moved. Both of those numbers were produced after the restart, and the restart is what had reset them. I had examined the patient after the cure and concluded there had never been a disease.

The second mistake outlived the first and is the one still true on your machine right now. To check whether something was eating memory I listed the largest processes. The biggest was 0.61 gigabytes, comfortably harmless, so I said so. But a modern application is not one process. My editor runs in twenty-three of them. Individually every one is unremarkable; together they held 5.2 gigabytes and were by a distance the largest thing on the machine — and they could not appear in a list of single processes no matter how far down I scrolled. The operating system’s own activity monitor sorts exactly the same way, which is why this hides so well: the tool you would reach for to check makes the identical mistake.

A third wrong conclusion was standing right next to those two and I nearly took it. Free memory had dropped by half, from eight gigabytes to four, which looks alarming and means almost nothing: the system uses spare memory as cache and hands it back on demand. So inside one small investigation there was a number invalidated by the fix, a number grouped by the wrong unit, and a number that looks frightening and is normal. None of them lied. All three were accurate and useless, which is a state that looks exactly like accurate and useful.

Pattern three

The body in the basement

What gets left behind when something goes wrong

The machine that runs my website audits kept getting slower, the way a room gets untidy. To read somebody’s site the tool opens a browser, looks, and closes it again — and the closing step was written as the last thing that happens, which means it happened only when everything before it had gone well. Other people’s websites are slow, or blocked, or gone, and every one of those failures left a browser standing. Counted rather than guessed: one failure in the middle of a job left four behind. After the repair the same measurement went seven to seven. The obvious reading of the symptom had been the flattering one — we are growing, time to pay for a bigger machine.

The other body was in the agent platform, and it is the one that changed how I read a green test. The code that executes a run existed twice. One copy, 295 lines, was carefully tested and called from nowhere in the entire repository. The copy that actually ran had no tests at all. Every green result was a statement about the wrong file, and every correction I made in response to a problem landed in the version nobody executes.

That is worse than having no tests, and it is worth being exact about why. With no tests you know you are exposed and you behave accordingly. With tests on the wrong file you have a cheerful running signal telling you the area is safe, and the attention that would have found the problem goes somewhere else. When I finally pointed the tests at the code that runs, two of them failed on the first attempt and reproduced a fault I had not known about: a failure in one branch marked the whole run finished while its siblings were still working, and they then wrote their results into a run that had already been closed. From outside, a failed run and a running run looked identical. Nothing said stuck. You waited, and waiting was indistinguishable from working.

Pattern four

The impatient hand

The right work in the wrong order

Pressing delete on a card in my video tool did nothing for one to two minutes, so people pressed it again. The natural reading is impatience, or a slow interface. Neither was true. Before doing any of its own work, the button first waited on a membership check against another company — with a cold cache, roughly thirty requests in a row, and no time limit on any of them. Only after all of that did it do the one thing that had been asked of it, which takes no time at all.

Sitting above that code was a note saying the third-party work runs in the background. The note was correct — about the tidying that happens afterwards. It was not correct about the check in front, and it had been read as covering both for as long as it had existed. A comment that is simply wrong gets found eventually, because it contradicts the code beside it. A comment that is true about one half of what it describes is not wrong, so nobody corrects it, and it goes on quietly answering a question it was never about.

What all six have in common

Five of the six were found by something other than the thing that was supposed to find them: a checker running for the first time, an unrelated count, a second pass that was about to repeat the same mistake, a look at the list of processes on the machine. The sixth was reported by me, after I had already published the wrong explanation for it.

And I cannot tell you what any of it cost. That is not modesty, it is the same fault one level up. Nobody recorded the signup attempts during those twelve days, because the thing that records them was the thing that was broken. There is no version of this where I go back and count. The most expensive property of a quiet failure is that it destroys the evidence of itself, which is precisely why it stays quiet — and why the honest answer to “what did it cost” is often that the question can no longer be answered.

The purest example of the whole set is not in the four patterns above, because it happened before I started grouping them. A guard killed the run that was carrying its own finding, and because it killed it, nobody noticed for nine nights. That one did not merely fail to report. It actively destroyed the report that would have exposed it.

The four questions, in the order I now ask them

Where does a success message stand in for a delivery? Go and look at the destination once. Not the log, not the confirmation screen — the place where the result was supposed to arrive.

What does each check literally compare, and what can it therefore never see? If the answer is a list of names, ask who adds to that list and when. If the answer is “whoever remembers”, you have found the gap.

What is left behind when something fails? Count the things that should have ended, not the things that reported an error. Residue never appears in a list of errors, because it is not one.

What waits on somebody else before it answers? And what is the time limit? If nobody knows, there is not one, and your worst case is a stranger’s bad afternoon.

None of these questions is clever. They are cheap, they are boring, and every one of them was learned by not asking it. They are also the first thing worth asking about any system you did not build yourself, before touching anything, because the answers usually explain more than the code does. Four questions, an afternoon, and you know whether the green lights mean anything.

Every figure here is measured and traceable to a commit: the twelve days and the single character to the repair of 6 September 2026; the memory numbers — 0.61 gigabytes for the largest process, 23 processes for one editor, 5.2 gigabytes summed — to 13 August; the browser counts of three to seven, and seven to seven after the fix, to 16 August; the 295-line dead copy and the two tests that failed on their first run to 17 August; the roughly thirty sequential calls and the one-to-two-minute delay to 31 August; the seventy-one of seventy-one published posts to a measurement of 6 September. The grouping into four patterns is mine and is the only part of this page that is an opinion rather than a measurement. What any of it cost is not measured and in several cases cannot be recovered.

Georg Singer

Georg Singer

I automate my own projects in public and write down what each one cost. Physics degree, doctorate in computer science, nine systems in production on hardware I own, all of it built in my own time.

More from the log