← all articles

Undecided Is Not The Same As Resolved

Undecided Is Not The Same As Resolved

The most dangerous decisions a system makes are the ones nobody notices it made. I was recently pulled into a case where a piece of retail software processed a refund at the counter, moved the money straight out of the till, and wrote it into the books as an ordinary transaction. Mechanically, everything worked. Commercially, something quietly went missing: nobody had actually decided whether the business absorbed that refund or recovered it from whoever supplied the goods. The system had an answer ready by default, gave it without asking, and by the time anyone looked at the numbers, the question had already been folded into "sale" and stopped looking like a question at all.

That is the pattern worth naming, because it shows up everywhere software touches money, risk or responsibility: a default action gets taken because something has to happen right now, and the record of that action ends up looking identical to a record of a decision that was actually made. Those are not the same thing, and treating them as the same thing is how organisations lose track of who owes what, who approved what, and who is supposed to be accountable for what.

The instinct when you spot this is to make the software smarter — have it work out automatically who should bear the cost, based on rules, history, or some scoring model. Resist that instinct until you have done the more boring thing first, which is simply making the undecided state visible and durable. Before the refund system tried to get cleverer, it needed to stop letting a default masquerade as an answer. The fix wasn't an algorithm that decided whose cost it was. It was a change that let the money move immediately, because a customer standing at a counter cannot wait on a policy debate, while separately and durably recording that a decision about who bears it was still open, tagged, and routed to whoever actually holds the authority to close it out.

That separation matters more than it sounds like it should, because the two failure modes it prevents are genuinely different. One is the failure of blocking the action entirely until a human signs off — which is safe on paper and useless in practice, because nobody designs a checkout process that pauses a refund while someone reads an email. The other, more common failure is letting the mechanical action stand in for the judgment call, so the system's convenience becomes the organisation's policy by accident. Six months later someone asks why the business has been quietly eating every refund cost, and the honest answer is that nobody chose that. A default chose it, on a Tuesday, because building the "who pays" logic properly felt like it could wait.

I think a lot about defaults for this reason. A default is not the absence of a decision — it is a decision, made in advance, usually by whoever wrote the code, and it applies every single time the harder question doesn't get asked. The trouble is that a default doesn't feel like a decision to the person who benefits from the shortcut. It feels like nothing happened, when in fact something happened repeatedly, at scale, without anyone in the room. Good systems earn trust by keeping that distinction sharp: an action can proceed on a sensible default while the record insists, unambiguously, that the underlying judgment call is still open until a specific person with the authority to close it actually closes it.

There's a practical discipline in this that's worth carrying into any system where an automatic action has a consequence someone might later dispute — a refund, a discount override, a retry that silently changes an outcome, an AI agent taking an action on someone's behalf. Ask, before you ship the convenient path, whether the record it leaves behind can be told apart from a record of genuine agreement. If a compliance officer, an auditor, or simply next quarter's version of you looked at that entry, would they be able to tell it was a default rather than a considered choice? If the answer is no, you haven't automated a decision — you've hidden one.

The other half of this discipline is remembering that "pending" is a legitimate, first-class state, not a failure to finish the job. It's tempting to treat every open item as technical debt to be swept up later, and plenty of teams build systems that quietly reassign or auto-close things that sit unresolved for too long, because an aging queue of open decisions looks bad on a dashboard. But collapsing a genuinely undecided thing into a resolved-looking one doesn't remove the risk — it just removes the visibility of the risk, right up until the moment it turns out to matter. A reminder that nags the right person after a sensible grace period is a far better answer than a status field that silently flips itself to "handled."

None of this is really about refunds, or tills, or any particular piece of software. It's about a much older habit that technology makes easy to smuggle in at scale: mistaking the fact that something moved for the fact that someone agreed it should. Money left a drawer and the ledger called it ordinary business. A default fired and the dashboard called it done. An AI system produced a plausible answer and everyone downstream treated it as settled fact. In every version of this story, the fix is the same unglamorous thing — build the seam that keeps "this happened" and "this was decided" as two separate, checkable claims, so that when they genuinely diverge, the system tells you instead of quietly agreeing to forget.

That seam costs a little extra design effort up front, and it rarely shows up in a demo, because a working default already looks finished. But the businesses that hold up under scrutiny are usually the ones that can point to exactly who decided what, and when, rather than the ones that were simply lucky that their defaults never got questioned. Building software that keeps that line honest is one of the more underrated forms of care you can put into a product — not because it's clever, but because it's the difference between a business that can explain itself and one that's hoping nobody asks.

Matthew Ratcliffe, software developer and architect, Ballarat
Senior Software Engineer & Architect

20+ years across the technology stack — from greenfield builds to brownfield rescues. Based in Ballarat, VIC, focused on AI, healthcare and high-risk data systems. Full resume →

Share your thoughts