Matching a bank line to the thing it paid for
A bank statement gives a date, an amount and a scrap of text. Turning that into "this paid that invoice" is a guess, and the rules around the guess matter.
A bank statement line contains a date, an amount, a direction, and a fragment of text produced by a system that was not designed to help you.
Somewhere in your records is the thing that line paid for. Connecting the two is bank reconciliation, and although it is treated as clerical work, it is mostly inference — which means it can be wrong, and being wrong has consequences that outlive the mistake.
What evidence actually exists#
Four kinds, of very different quality.
An exact amount match. Strong, when amounts are distinctive. Weak when they are round numbers, because round numbers recur.
A reference in the narration. The strongest evidence there is, when it exists. It usually does not, or it exists in a mangled form. Receipts from flat buyers are the same problem in bulk, arriving against a reference printed on the demand letter and almost never quoted back.
A name in the narration. Good, if you can map bank narration strings to your vendors. Those strings are inconsistent, abbreviated and occasionally belong to a payment processor rather than the vendor.
Timing and recency. The weakest. Everything that happened this week is temporally close to everything else that happened this week.
The failure mode is treating a weak signal as sufficient because no strong one is available.
The near-miss amount#
We built a matcher that got this wrong, in a way worth describing because the mistake is so natural.
A transfer came in at an amount close to — but not equal to — the amount outstanding on a particular order. The matcher proposed the two as a pair, on nothing but that closeness. Its own explanation for the proposal read, in effect, no name, but the amount is close.
Close amounts are extremely common. Any organisation with a few hundred open items has several within a few per cent of any given figure, and a rule that accepts closeness will pair transactions with orders that have nothing to do with each other.
The rule now is that a near-miss amount alone is not evidence. It needs something beside it — a vendor name in the narration, a known alias, a label learnt from a previous confirmed match. An exact match still stands on its own, and so does an amount that reconciles arithmetically with tax added, because that is a computed relationship rather than a coincidence.
The general principle: closeness is not evidence, it is an absence of contradiction. Those feel similar and are not remotely the same thing.
The candidate pool that never emptied#
The second fault we found was subtler and had been quietly poisoning matches for months.
A payment made in stages never set the field meaning this is paid, because when a payment has a schedule, the stages are the payment record. So a fully settled order stayed in the matcher's candidate pool for ever, at its full original amount, permanently available to be matched against some future transaction that happened to be near it.
The pool was not a list of things awaiting payment. It was a list of everything that had ever awaited payment, and it grew without limit.
The correction was to treat a fully answered schedule as a settlement timed at its last stage, kept in the pool only through the same short proof window a hand-marked payment gets, and to make "remaining" actually subtract the advance. The same missing fact had leaked into eight other places in the application; the whole account is a fact that had no owner, and the version of it aimed at accounting systems is why staged payments break accounting systems.
Never attach on the machine's own authority#
This is the rule we hold to hardest, and it came from the owner of the business rather than from the engineering side: never auto-link anything.
A machine match is recorded as a suggestion. It carries its score and its reasoning. A person taps to confirm or to reject, and both answers are permanent — a rejection is remembered so the same wrong pair is never proposed again.
The reason is not that machines are unreliable. It is that an automatic attachment leaves behind a record indistinguishable from a human decision. Six months later somebody reads "this transaction paid that invoice" and has no way of knowing that nobody ever agreed. The error is not the wrong pairing; it is the false confidence in the record afterwards. That argument, in full, is the machine proposes, a person decides.
When we adopted this rule we also had to convert matches the machine had already made on its own authority back into suggestions, in the same migration that introduced the rule. There is no honest alternative: a record created by a mechanism you have since decided was not trustworthy does not become trustworthy by being old.
The evidence floor has to be everywhere#
A subtlety that cost us a round of fixes: it is not enough for the main matcher to have a high evidence standard.
The same suggestions appeared in a second place — a per-row list on the money page — and that list had been written separately, with its own scoring, at a lower threshold. So a pairing the main matcher would have refused was being offered as a one-tap action somewhere else in the application.
One rule, one implementation, asked by every surface. Two implementations of the same rule will diverge, and the divergence is silent because each is internally consistent.
Undo must be complete#
When somebody attaches a transaction and then undoes it, the undo has to clear everything the attachment created: the comment, the notification, and the open suggestion it answered.
We found that a stale suggestion card kept rendering on a task the money had never belonged to, because undoing the attachment did not close the question that prompted it. Half-undone states are worse than either the original error or a clean reversal, because they present as current information.
What a good matcher looks like#
- Exact matches, proposed with high confidence, still confirmed by a person.
- Near matches, proposed only with corroborating evidence, with the reasoning shown.
- No proposal at all where the evidence floor is not met — an honest empty result rather than a weak guess.
- Rejections remembered permanently.
- One implementation of the rule, asked by every screen.
- Complete undo.
None of that is clever. All of it is the difference between a reconciliation that saves work and one that creates a category of quiet error nobody can find later.
The short version#
Matching a bank line is inference from weak evidence. Amount closeness is not evidence. A candidate pool that never empties will eventually match something wrongly.
And whatever the machine concludes, a person taps. The cost of an automatic wrong link is not the link. It is that it looks like somebody decided.