SYSTEM DESIGN · QUESTION 109
How would you design a reliable payment processing system?
On this page
I would clarify payment methods, authorization versus capture, refunds, consistency, and audit needs. Create a durable payment intent with an idempotency key, validate the request, and coordinate provider calls through explicit states and an outbox or workflow. Handle timeouts as unknown outcomes, reconcile with the provider, and keep an immutable ledger. Never assume a network retry means the first attempt failed.
LET'S MAKE IT SIMPLE
First, the idea in plain English
A payment request may reach a provider even if the response gets lost. If the application retries as a new charge, the customer may be charged twice. The system needs a stable payment identity, clear state transitions, and reconciliation for cases where the result is uncertain.
A USEFUL COMPARISON
Picture it this way
A bank transfer receipt has a transaction reference so the bank can check whether a request already happened after a connection drops. The system must distinguish “not processed” from “processed but response missing.”
FOLLOW THE JOURNEY
Track payment intent and reconcile uncertain provider outcomes
Show idempotent request handling, provider interaction, state transitions, and ledger recording.
This simplified visual highlights the main relationships. In practice, the exact design depends on the requirements; Do not infer success or failure from a missing response.
A client creates an idempotent payment intent; a workflow calls a payment provider, records authorization or uncertainty, reconciles status, and posts ledger entries.
How to read this visual
This simplified visual highlights the main relationships. In practice, the exact design depends on the requirements; Do not infer success or failure from a missing response.
UNDER THE HOOD
How it works, step by step
Create intent
Validate amount, currency, identity, and idempotency key.
Why it matters: A stable intent anchors retries and audit.
Call provider safely
Authorize or capture with bounded timeouts and provider idempotency.
Why it matters: Network failure may leave the outcome unknown.
Record state and ledger
Persist transitions and immutable financial entries.
Why it matters: Financial history needs traceability and reconciliation.
Reconcile and notify
Query provider status and publish confirmed outcomes.
Why it matters: Do not infer success or failure from a missing response.
OUTSIDE THE TEXTBOOK
A practical example
A customer submits a card payment and the provider times out after receiving it. The service marks the attempt as pending or unknown, then checks provider status using the same idempotency key before retrying. It posts a ledger entry only from a confirmed state and communicates the eventual result.
GO A LITTLE DEEPER
Technical details that matter
- Payment intent state machines should make valid transitions explicit and auditable.
- The transactional outbox can ensure database state and event publication remain consistent.
- A ledger records balanced immutable entries; corrections are represented as compensating entries rather than rewriting history.
MAKE A GOOD CHOICE
When is this useful?
- Checkout, subscriptions, transfers, and refunds.
- Any workflow with external financial side effects and retries.
- Systems requiring audit trails and reconciliation.
Use a trusted payment processor’s hosted checkout when it meets product requirements and reduces sensitive-card-data handling.
WATCH OUT FOR
Common misunderstandings
- Retrying a timed-out charge with a new request identity.
- Treating authorization as settlement or capture.
- Updating balances without a durable ledger and reconciliation process.
REAL-WORLD TRADE-OFFS
Limitations and failure cases
- Provider outcomes can remain unknown temporarily.
- Financial workflows require strict audit, privacy, and compliance controls.
- Cross-system transactions are not generally atomic.
WHAT TO REMEMBER
Key takeaways
- 1Use durable payment intents and idempotency keys.
- 2Treat timeouts as uncertain until reconciled.
- 3Maintain explicit states, immutable ledger entries, and provider reconciliation.
PRACTICE THE FOLLOW-UP
What might an interviewer ask next?
What should happen after a provider timeout?
Keep the outcome pending or unknown, then query or reconcile with the provider using the same idempotency identity before attempting another charge.
Why use a ledger?
It provides an auditable history of financial changes and supports reconciliation; balances can be derived or checked against entries.
SAY IT OUT LOUD
How to explain this in an interview
“I would model a durable payment intent with an idempotency key and explicit authorization, capture, refund, and failure states. A timeout is an unknown outcome, not proof the provider did nothing, so I reconcile before retrying. I keep an immutable ledger and audit trail, and publish confirmed outcomes through a reliable workflow.”
Connect this question to the roadmap topic it supports.