Your choices about data
We use cookies that are required for this site to work. Anything beyond that — measuring how the site is used, or personalising what you see — happens only if you say yes.
Retiring a payment processor
Removing a vendor is easy. Replacing
See how payments workTHE THING NOBODY WROTE DOWN
The old processor took every tender in one call.
A cart paid with a gift card and a credit card went to the vendor as one array and came back as one result. Either both moved or neither did, and nothing in our code had to arrange that. It was never written in a design document because it was never a decision — it was a property of the endpoint. Those are the guarantees you discover by removing them.
Talk to usWHAT REPLACED IT
Sequential, with compensation — and it is genuinely worse.
Gift cards are reserved first, the remainder is authorized through the gateway, and if that authorization fails every reservation is released. It works, and it is not equivalent: a crash between the reserve and the authorize leaves a hold on someone's card that only expiry cleans up. We could hide that behind the word 'eventually'. It is more useful to say that atomicity across a database we own and a processor we do not would need a distributed transaction, and we chose not to build one.
Talk to usTHE ONE THAT MATTERED
A counter is not a document.
Bringing gift cards in-house meant deciding how two simultaneous checkouts share one balance. The cart uses optimistic locking, because a cart is a document rewritten whole. A gift card is a counter, and a counter wants a single guarded statement — decrement where the balance is still sufficient, and read how many rows changed. We proved it by replacing that statement with the obvious read-then-write and watching two concurrent reserves both succeed: the same balance spent twice.
Talk to usA passing test is not evidence that it would catch the bug.
Every guard in that migration was checked by reintroducing the defect it existed for and confirming the test failed. Two of them would otherwise have been decoration: the concurrency guard above, and an amount conversion — the old processor spoke major units and the new one speaks minor, so copying the divide-by-one-hundred would have charged every customer one percent of what they owed, and reconciled perfectly against every round number in the test suite.