The original design was the obvious one. A transaction arrived, we looked up the cardholder, looked up their policy, evaluated the rules, and wrote the result. It worked, and it was wrong in a way that took us a long time to see.
Evaluation after the fact is a guess about the past
The lookup happens now. The policy it finds is today’s policy. The transaction happened three days ago, possibly under different rules, and reconstructing which rules were in force at authorisation meant versioning the policy and joining on time — which we did, and which was correct, and which nobody could reason about.
Worse, the answer could change. Re-running the same evaluation next week could produce a different coding for a transaction already in the books, because someone edited a policy in between. A ledger where yesterday’s entries can move is not a ledger.
Deciding at issue instead
The change was to resolve the policy when the card is issued and write the outcome onto the card: allowed categories, the two caps, the account and cost centre. The authorisation carries them. The settled transaction carries them.
Three consequences, only one of which we predicted:
- Coding stopped being a computation and became a field, so the close has nothing to recompute.
- Policy edits stopped being retroactive by default, because a change now applies to cards from the moment it is applied to them.
- Support volume fell, because “why was this coded to marketing?” became answerable from the transaction alone rather than from a policy history.
What it cost
Re-issuing. A policy change that must apply to existing cards has to walk them and update each one, and that is a real background job with real failure modes — where before it was one row in a table. We consider it a good trade: the cost moved to the moment somebody makes a change, which is a moment somebody is present and paying attention, and away from the close, which is a moment nobody has slack.
The general shape
Push the decision to the earliest point where all the inputs exist. Anything decided later has to be re-decidable, and anything re-decidable is something the close has to defend.





