AI agents for SMEs - now running in production. See how the pilot works →

Transaction integrity when partners spend a wallet balance

The naive implementation of a partner booking channel is two steps: debit the wallet, then create the booking. It is obvious, it reads well in a specification, and it is wrong.

At any volume the second step will sometimes fail – a validation error, a lock timeout, a dropped connection. The partner has then paid for nothing. They find out days later, support cannot explain it, and finance has a discrepancy with no audit trail. Reverse the order and you get the opposite failure: a booking exists that nobody paid for.

Both states have to be impossible

The requirement is not “handle the error”. It is that the intermediate state should not be representable. Balance validation, the wallet debit and the booking write belong in a single database transaction, so either all three commit or none do.

Three details matter more than the transaction itself:

  • Lock ordering. If one code path locks the wallet then the inventory, and another locks inventory then wallet, you have a deadlock waiting for concurrent load. Pick an order and enforce it everywhere.
  • Foreign key constraints, not application checks. A constraint makes the invalid state impossible. An application check makes it unlikely, which is a different guarantee.
  • Read the balance inside the transaction. A balance checked before the transaction opens is a stale balance, and two concurrent bookings can each pass a check that neither should.

Credit limits change the shape of the problem

A prepaid wallet has a floor at zero. Introduce a credit limit and the floor moves, which means the available figure is a function of balance, limit, and any bookings still in flight. Storing “available credit” as a column invites it drifting out of step with reality. Deriving it inside the transaction is slower and correct.

What the partner needs to see

The engineering above is invisible if the partner cannot verify their own position. The portal has to show live balance, credit headroom, and a statement where every line is labelled by movement type – booking, top-up, refund, adjustment. Automated notification on every movement removes the daily reconciliation phone calls that otherwise substitute for a system of record.

On the system we built this for, that was the actual outcome. Not a faster booking flow – the elimination of a category of conversation. Both sides could see the same record, so there was nothing to dispute.

Leave a comment

Your email address will not be published. Required fields are marked *

Book a consultation