Payments & ledgers
Payment gateway - what a timeout means when the card may already be charged
Teaches how a payment system stays correct when its authoritative dependency can fail in a way that tells you nothing.
What this board gets wrong on purpose
The tension
Every retry inside our own boundary is safe - the UNIQUE on idempotency_key sees to that - and none of it helps with the case the board is actually about. When the acquirer times out, the payment sits in UNKNOWN and the only thing that can resolve it is the acquirer itself: either a webhook it may never send, or the settlement file that lands T+1. So a payment can be unresolved for thirty hours, with the cardholder holding a pending debit and the merchant holding no answer, and the design has no way to shorten that window because the fact it needs is not in any database it owns. Worse, the repair loop is drawn with a single reconciliation worker reading a single file: if the file is late, malformed, or the worker crashes halfway through, nothing on this board notices, and the UNKNOWN pile grows silently until a human reads a dashboard. The status-inquiry call to the PSP would cut the window to minutes, and it is not on this board because it is rate-limited to a few hundred a minute and the peak produces thousands of unknowns - so the fix exists and does not fit.
1 · Requirements
A gateway sits between a merchant who wants a yes/no and an acquirer who will sometimes give neither. It owns exactly one thing: an honest, durable record of every attempt to move money, and the discipline never to guess at one.
Ask these before designing
- Are we the merchant of record, or a technical gateway? If we hold the funds we owe a ledger, settlement, payouts and a regulator. If we only route, we owe an audit trail and nothing else. The answer changes whether half this board exists.
- Auth-then-capture, or sale? A separate capture is what lets a shipped-in-three-days business take the money when it ships. It also creates a second network call that can time out, and a 7-day expiry on the authorisation. A single "sale" call halves the failure surface and removes the option.
- How many acquirers? One acquirer is one outage away from zero revenue. Two acquirers means routing logic, two idempotency dialects, two reconciliation formats, and two settlement calendars.
- Does the merchant expect a synchronous answer? If yes, the UNKNOWN case has to be resolved into a lie or a 202. If the merchant will accept a webhook, UNKNOWN can be told honestly and the whole design gets simpler.
- What is the refund window? 120 days of refundability means captures stay addressable for 120 days, which is a retention requirement disguised as a product decision.
Functional
- Authorise a card for an amount, returning a stable payment id.
- Capture all or part of an authorisation, once.
- Refund all or part of a capture, any number of times up to the captured total.
- A retried request with the same Idempotency-Key returns the first answer and performs no second money movement.
- Every state change is an appended event with the acquirer reference that caused it.
- Reconcile against the acquirer daily and report every disagreement.
Non-functional
- Never double-charge, even at the cost of declining. A duplicate charge costs the chargeback, the refund, the fee, the support contact and the merchant relationship. A false decline costs one retry.
- p99 under 3.5 s for POST /payments, of which the acquirer is 2.1 s and is not ours. Our own budget is 400 ms.
- 99.99% on the authorisation path (52 min/year) measured as "we returned a definite answer or an honest 202", not as "we returned 200".
- Zero tolerance for lost writes. Synchronous replication before we acknowledge, always. A payment we acknowledged and then lost is indistinguishable from fraud in an audit.
- Every amount is an integer of minor units with an ISO 4217 currency. Floats are not a rounding inconvenience here, they are a reconciliation break.
Explicitly out of scope
Fraud scoring (its own board), 3-D Secure step-up flows, tokenised wallet decryption, merchant onboarding and KYC, payout scheduling. Each is real; none changes the shape of the timeout problem.
The rest of this board
Available on Tier Slate
This page publishes the question. The answer — 5 more written pages, a 9-step narrated walkthrough and a 5-table schema — is the board itself, and it opens in Tierslate.
- 5written pages
- 9walkthrough steps
- 5tables35 columns
5 pages behind this one
- Capacity estimation
- Storage estimation
- Availability
- How it works
- Deployment plan
More boards
Systems where losing a write is losing money.