A Bug Is A Question About Who Pays

I watched a small argument play out recently that is worth more attention than it usually gets: is this a bug, or isn't it? A system had done exactly what it was built to do. Someone cancelled a record that was sitting in a batch, and the system removed it, the way it was designed to. Nothing crashed. Nothing violated its own logic. And yet a person on the other side of that action had lost something real — usage data tied to that record — and now wanted to know why the software had let that happen. Half the room said "working as designed." The other half said "that's clearly a bug." Both were right, and both were asking the wrong question.
The question that actually matters isn't whether the behaviour matches the specification. It's who ends up carrying the cost when the behaviour, however correct, produces an outcome nobody wanted. That reframing changes almost everything about how a team should triage, prioritise and talk about the problems it finds.
Most defect taxonomies are built around intent. Did the code do what the design said it should do? If yes, it's not a bug, it's a feature gap or a change request, and it goes into a slower queue with a different owner and a different level of urgency. If no, it's a bug, and it gets fixed. This is a tidy model, and it is tidy specifically because it is convenient for the people building the system. It asks nothing about the experience of the person using it. A specification is a snapshot of what someone understood and could articulate at a point in the past. It is not a promise that every consequence of following it precisely will be acceptable, and treating conformance to it as the entire test of correctness quietly optimises for the engineer's peace of mind over the user's actual outcome.
I've come to prefer a different first question: what did this cost the person who hit it, and can they get it back? In the case I watched, the answer was blunt. Real information, tied to a real event, was gone, with no undo and no trace that it had ever existed. That's not a UX nit or a nice-to-have. That's the software silently deciding that a category of loss was acceptable, on behalf of someone who never agreed to that trade. Once you ask the question that way, the "working as designed" defence stops being a defence at all. It becomes an admission that the design never considered this cost in the first place, which is a different and more useful thing to know than whether a ticket gets labelled correctly.
This matters because the label a team puts on a problem determines almost everything that happens to it afterwards. Call it a bug and it usually gets triaged against a severity scale that asks about broken functionality, data corruption, security exposure — things with sharp edges. Call it a feature request or a design gap and it goes into a backlog that gets reprioritised every planning cycle against a hundred other ideas, most of which are about adding capability rather than removing harm. A genuine loss of data, dressed up as a scope question because the system behaved as documented, can sit in that second queue for months, quietly costing someone something every time it happens, purely because of which door it walked through on day one.
The uncomfortable part is that this isn't a process failure so much as a natural consequence of how specifications get written. Nobody sits down at the start of a project and enumerates every state a batched, cancellable, partially-processed record can end up in, because nobody can. The specification captures the paths the team thought about. Reality finds the paths it didn't. When reality finds one of those gaps, the fact that the code faithfully implements the incomplete specification is not evidence that everything is fine — it's evidence that the specification was incomplete, which is a completely ordinary and unavoidable thing to be true of any specification written by people who cannot see the future. Treating "matches the spec" as a permanent shield against the word "defect" punishes users for a limitation that was never their fault to begin with.
None of this means every unwanted outcome deserves the urgency of a P1. Plenty of gaps are genuinely minor, genuinely reversible, or genuinely rare enough that a considered backlog item is the right call, and screaming "bug" at every rough edge just trains a team to stop listening. The point isn't to inflate every gap into an emergency. It's to replace the wrong triage question — does this match what we said we'd build — with the right one: what does this cost someone, is that cost recoverable, and did anyone actually choose to accept it on the user's behalf. A cost that's small and reversible can sit in the backlog with a clear conscience. A cost that's real, irreversible, and was never consciously chosen by anyone deserves urgency regardless of which side of the specification line it falls on.
There's a commercial angle here too, because engineering time is not free and not every gap is worth closing immediately. A team that fixes every deviation from user expectation with the same urgency will never ship anything else. But a team that only ever asks "did the code do what we told it to" will systematically under-invest in exactly the failures that erode trust the fastest, because those failures are, almost by definition, the ones nobody thought to write into the specification. The cases that quietly cost someone something real and permanent are rare enough that fixing them properly is usually cheap relative to the damage of leaving them, and common enough across any system's lifetime that ignoring the pattern adds up.
The most useful thing that came out of the conversation I watched wasn't a resolution about whether to call it a bug. It was somebody asking, almost as an aside, whether the person who lost that data had been told it was gone, or had simply discovered it missing later. That's the real test, in my experience, of whether a team has actually reckoned with what its software costs people rather than just what its software was told to do. If nobody would need to be told, because nothing bad happened to them, argue about the label all you like — it genuinely doesn't matter. If someone would need to be told, that's already your answer. Fix it, and worry about what to call it afterwards.


Share your thoughts