One number. Four answers.
29 July – 3 August 2026. Written 8 August 2026.
We agreed what one of the business’s core figures meant, built it, and shipped it into exactly one screen — and it was not the screen the decision-maker reads.
The owner of the business told us that the ageing calculation had already been discussed and finalised, and asked why the figure on his screen was still wrong. He was right on both counts, and that is what makes this worth writing down rather than quietly fixing. The definition had been agreed. We had built it. We had built it into one screen, and left every other screen showing the same label to carry whatever arithmetic it had always used.
This is our live product — reps, dealers, suppliers and a head-office desk across a 93-branch commercial-vehicle parts distributor, sitting on top of a twenty-year-old VB.NET ERP of roughly 1.1 million lines. In production every day since July 2026.
When we counted, one headline receivables figure — the kind every distributor watches, and the one this business watches most — had four live answers on the same product at the same time.
The company ageing bar took each bill’s age, gross, and bucketed each bill separately. That was the agreed definition. Beside it sat a netted variant of the same bar, credit notes subtracted. A third worked at dealer level, measuring days past terms rather than bill age. The fourth was the exceptions row on the head-office dashboard — computed separately from all three, and the furthest of the four from the answer we had agreed.
That outlier deviated three ways at once, and the deviations compounded. It aged money from the due date rather than the invoice date, which on normal trade terms is weeks of difference. It bucketed per dealer rather than per bill, so a dealer’s entire balance landed in the bucket of their worst invoice. And it netted credit notes out. Each of those three choices is defensible on its own. Together they answer a different question, under the same words.
Nothing was broken. No test failed, no alert fired, no query errored, every screen rendered, and each of the four numbers was internally consistent and entirely plausible. Nothing in the product had any notion that two of its own figures were meant to agree, so nothing could notice that they did not. It was found the only way it could have been found: a person put two screens carrying the same label side by side and saw different money. What reads as a process complaint was a precise and correct bug report.
The cause was not a coding slip. A line on our own backlog read, in effect, one place that owns this figure. We had written it down and recognised it as right. We skipped it, more than once, in favour of shipping screens — because it would have produced no new screen of its own. That is the mistake, and the incentive behind it is worth naming plainly: the work that stops a number drifting is invisible on the day you do it, and becomes visible only on the day someone loses faith in a figure. We took the visible work. Meanwhile the definition we had agreed went onto a screen the decision-maker does not use, while the screen he does use carried the oldest and most divergent version. Nobody had checked which screen the person complaining was reading.
Before — the arithmetic lived inside each screen
- Headline barbill age · gross · per bill
- Netted barbill age · net · per bill
- Dealer viewdays past terms · net · per dealer
- Dashboard rowthe same basis — computed all over again
After — the arithmetic lives once, upstream
- One pass, one bucketing ruleproduces a company band and a per-dealer figure
All four screens now read that one computation. None of them compute anything.
The per-dealer figure and its bill count are now produced inside the same single pass over the bill list, through the same bucketing rule, as the company-level band. The headline bar, the exceptions row and the drill-down beneath it are no longer three implementations that happen to agree; they are one piece of arithmetic displayed three times, and cannot disagree. We checked it against the full book: the two independently assembled totals landed one rupee apart — per-dealer rounding — with identical bill counts. We relabelled the row so it states the basis it measures instead of implying a different one. We also had to apply the fix twice, because the first pass corrected the arithmetic without correcting the selection that decided which records the arithmetic ran over.
One detail worth copying: a total must sum over every record the definition covers, not only the ones the list happens to show. Rows can be filtered out of a display for good reasons and still belong in its total — and if they are dropped from both, the headline and the detail drift apart again, which is the entire bug.
There is a second mistake here, and it is the better one. The check we wrote to stop this recurring — a standing comparison that fires when two figures that must match do not — was written to abort the data build. It fired on real data. It killed every rebuild for hours. So while fixing a stale number we froze the whole product on stale numbers, and the figure that started all this sat at its old value all afternoon. We turned a reporting defect into an availability one, in the middle of fixing the reporting defect. The check now warns loudly and lets the build finish.
A guard on a number must never be able to take the product down. Stale but consistent beats confidently absent.
A refused build hands every user yesterday’s data on every screen — far worse than the discrepancy it was looking for.
Three days later, on 1–3 August, we went looking on purpose and found seven more places that had each hand-written their own answer to “what does this dealer owe” — a rep’s home band, the credit strip on the order screen, an export, a review list, an exposure view among them — all now behind one server-side definition and one front-end pair. One habit came out of the same week: a code release and a data rebuild land at different times, so a screen must confirm a newly added figure is really there before it depends on it.
The last decision is the one we would most like a sceptical reader to check us on, because it is where we deliberately did not unify. The figure a screen reports and the figure a control acts on are two different questions, and we left them on different bases on purpose. Collapsing them would have changed who the control applies to — a policy change wearing an engineering cleanup’s clothes. That is the owner’s call, not ours. Until he makes it, each figure states which question it answers.
A number with no owner will disagree with itself. Agreeing a definition is not the same as owning one: unless one piece of code computes a business figure and everything else reads that computation, every screen re-derives it, and the derivations drift silently, because each is individually correct and nothing compares them. One version of the truth does not mean one number — it means one owner per number, every number stating its basis, and the line between an engineering decision and a business one drawn where the business can see it. All four of those answers were working software. The fix shipped no new screen at all. It moved a computation.
Questions about this go to hello@64arcs.com. A person replies within two working days.