System Design blueprint · Fintech & E-Commerce
Payment processing that never charges twice
Idempotency keys, a double-entry ledger and reconciliation keep money correct when networks fail.
- Steps
- 6
- Subjective questions
- 32
- Objective questions
- 32
The problem and the outcome
Problem: A timeout and a retry can charge a customer twice, or lose a payment that did go through.
Outcome: Exactly-once charges and a ledger that always balances with the provider.
Architecture
How it works, step by step
- The client sends the payment with a unique Idempotency-Key, so a retry never charges twice.
- The API checks the key first: a repeated request gets the first result back.
- The provider is called once; its answer can arrive late, or not at all.
- A double-entry ledger records the payment as pending, then settled, and is never edited in place.
- Webhooks deliver the final status; the handler verifies the signature before trusting it.
- A nightly job reconciles the ledger with provider reports and retries any mismatch.
Tech stack
- Stripe / Razorpay / Adyen (PSP)
- PostgreSQL ledger
- Idempotency-key table
- Signed webhooks
- Nightly reconciliation job
Key design decisions
- An Idempotency-Key on every payment request, stored with its result, so retries return the first answer.
- A double-entry, append-only ledger: every movement is a debit and a credit, and mistakes are fixed with new entries, never edits.
- Webhooks treated as the source of truth for the final status, verified by signature.
Common mistakes
- Treating a timeout as a failure and retrying with a new key, which charges twice.
- Storing money as floating-point numbers instead of integer minor units.
- Trusting the success page in the browser instead of the server-side webhook.
What to measure
- Payment success rate by method
- Duplicate-charge count (target: zero)
- Reconciliation mismatches per day
- Webhook processing delay
Most-asked interview questions
Subjective questions 32
1How do you make a payment API idempotent?Asked almost every time
The client sends a unique key per payment attempt. The server stores the key with the request hash and, once done, the response. A repeat with the same key returns the stored response instead of charging again; a repeat with a different body is rejected. Keys are unique-indexed, so two concurrent requests cannot both win.
2Why use a double-entry ledger?Asked almost every time
Every transaction is recorded as equal debits and credits across accounts, so the books always balance and any error shows up as an imbalance. It is append-only, which gives a full audit trail, and balances can be recomputed from entries at any time.
3Walk through the lifecycle of a card payment.Asked almost every time
The customer submits card details to the payment provider (tokenised, never touching your servers), you create a payment intent with an idempotency key, the provider authorises with the card network and issuer (possibly with 3-D Secure), you capture the funds (immediately or later), and settlement moves money to your account days later. Refunds and chargebacks can follow.
4How do you model payment states?Asked almost every time
As an explicit state machine: created, requires_action, authorised, captured, failed, refunded, partially_refunded, disputed. Only allowed transitions are applied, every change is recorded with its source event, and webhooks or API responses drive transitions idempotently.
5How do you handle webhooks from a payment provider reliably?Asked almost every time
Verify the signature, store the raw event with its ID, respond 2xx quickly, process asynchronously, deduplicate by event ID, tolerate out-of-order delivery by checking state, and reconcile periodically in case webhooks are missed.
6How do you keep the order and payment consistent?Asked almost every time
Use the payment provider as the source of truth for money, record the payment intent before calling it, update order status only from confirmed payment events, and run reconciliation jobs that compare your records with the provider's to fix any mismatch.
7How do idempotency keys make payment APIs safe to retry?Asked almost every time
The client sends a unique key with each payment request. The server stores the key with the request hash and result in the same transaction as the payment, and on a retry with the same key returns the stored result instead of charging again. A different body with a reused key is rejected.
8What do you do when the provider's response never arrives?Very often asked
Mark the payment pending, never failed. Query the provider's status API with the same idempotency key, and wait for the webhook. Reconciliation catches anything still unresolved. Only retry the charge with the same key.
9What is the difference between authorisation and capture?Very often asked
Authorisation reserves funds on the card without moving them; capture actually charges them. Separate capture suits marketplaces and shipping-on-dispatch, but authorisations expire after days, so capture in time or re-authorise.
10How do you stay PCI DSS compliant with minimal scope?Very often asked
Never let raw card numbers touch your servers: use the provider's hosted fields, checkout pages or SDKs that tokenise in the browser. Then you only handle tokens, which keeps you in the lightest compliance category.
11How do you handle refunds and partial refunds?Very often asked
Create refunds through the provider with an idempotency key, track refunded amounts against the captured amount, update the ledger with reversing entries, and only mark the order refunded when the provider confirms.
12How do you deal with chargebacks?Very often asked
Receive dispute webhooks, freeze related payouts if needed, gather evidence automatically (receipts, delivery proof, logs), submit it before the deadline, record outcomes in the ledger, and track dispute rates because high rates bring penalties.
13How do you handle multiple currencies?Very often asked
Store amounts in minor units with an ISO currency code, never mix currencies in one sum, record exchange rates used at the time of conversion, and settle in the currencies your provider supports.
14How would you design retries for failed payments?Very often asked
Retry only transient errors (network, timeout, rate limits) with the same idempotency key and backoff. Do not retry hard declines like insufficient funds automatically; for subscriptions use dunning schedules with customer notifications.
15How do subscriptions and recurring billing work?Very often asked
Store a payment method token with the customer's consent (mandate), create invoices per billing cycle, charge automatically, handle failures with dunning and grace periods, and apply proration when plans change mid-cycle.
16How do you design a double-entry ledger for a payments platform?Very often asked
Every money movement is a balanced transaction of debit and credit entries across accounts, such as customer, merchant, fees and settlement, so the sum is always zero. Entries are append-only; corrections are new reversing entries. Balances are derived from entries and reconciled against bank statements.
17How do you reconcile your records with the payment provider?Very often asked
Daily, download the provider's settlement and transaction reports, match each item to your payments by provider ID and amount, flag mismatches such as missing captures, unexpected refunds or fee differences, and route unresolved items to a finance queue with an owner.
18What is 3-D Secure and why does it matter?Often asked
An authentication step where the issuer verifies the cardholder (for example via an app or OTP). It shifts fraud liability to the issuer and is required for many transactions under rules like PSD2 SCA in Europe or RBI mandates in India.
19How do you detect payment fraud?Often asked
Use the provider's risk scoring, check velocity (many attempts per card or IP), mismatched addresses, unusual amounts and device fingerprints, block card-testing patterns with rate limits and CAPTCHA, and review high-risk orders manually.
20How do payouts in a marketplace work?Often asked
Collect payment into the platform, record each seller's share in the ledger, hold funds until delivery or a period passes, then pay out through the provider's connected accounts, handling fees, refunds and negative balances.
21Why should payment code be isolated as a service?Often asked
It needs stricter security, auditing and change control, has different scaling and availability needs, and isolating it keeps compliance scope small and protects it from unrelated bugs.
22What should be logged for payments?Often asked
Every API request and response (without card data), state transitions, webhooks with IDs, idempotency keys and correlation IDs, enough to reconstruct any transaction for support, audits and disputes.
23How do you test payment flows?Often asked
Use the provider's test mode and test cards for success, decline and 3-D Secure, replay recorded webhooks, test idempotency by sending duplicate requests, and run end-to-end tests in a sandbox before releases.
24What is a payment gateway vs. a payment processor?Often asked
The gateway securely collects and transmits payment details from the merchant; the processor communicates with card networks and banks to authorise and settle. Modern providers like Stripe or Razorpay bundle both.
25How would you handle a payment that times out with no response from the provider?Often asked
Mark it unknown, never failed, then query the provider with the same idempotency key or payment ID until it reports a final state, and rely on webhooks and reconciliation as backstops. Tell the user the payment is being confirmed rather than inviting a second attempt.
26How do you calculate and store taxes such as GST on payments?Often asked
Compute tax at checkout from the place of supply, product category and customer's tax ID using a versioned rules table or tax service, store the tax breakdown on the invoice line items, and never recompute old invoices when rates change.
27How do you let a customer change the card on a subscription?Often asked
Collect the new card through the provider's hosted fields or SDK, which returns a token or payment method ID, attach it to the customer, run a zero-amount or small authorisation to verify it if required, set it as default, and retry any open failed invoice on it.
28How do UPI payments differ from card payments?Sometimes asked
UPI moves money directly between bank accounts in real time through NPCI, with the customer approving in their UPI app; there is no separate authorisation and capture step, and failures or pending states need status checks and reconciliation.
29How long should payment records be kept?Sometimes asked
As long as tax, accounting and regulatory rules require (often several years), with sensitive data minimised, encrypted and access-controlled.
30How do you show payment status to users clearly?Sometimes asked
Show pending, success or failure with next steps, avoid asking users to pay again while a payment is pending, and send receipts by email once confirmed.
31What metrics matter for a payment system?Sometimes asked
Authorisation and success rates by method and issuer, latency, error types, refund and dispute rates, reconciliation mismatches and revenue per day, with alerts on sudden drops.
32How do you handle currency conversion for an international checkout?Sometimes asked
Show the price in the buyer's currency using a rate locked for a short window, store both the presented amount and the settlement amount with the rate used, and let the provider or bank do the actual conversion. Record FX gains or losses in the ledger.
Objective questions 32
1How should money amounts be stored?Asked almost every time
Why: Integers avoid floating-point rounding errors; 10.10 is stored as 1010 paise.
2Who should handle raw card numbers?Asked almost every time
Why: This keeps PCI scope minimal.
3What should a webhook handler do first?Asked almost every time
Why: Unsigned events could be forged.
4What is the source of truth for whether money moved?Asked almost every time
Why: Redirects can be faked or lost.
5What should a server return for a retried request with the same idempotency key?Asked almost every time
Why: Retries must not move money twice.
6Before trusting a webhook, the handler must…Very often asked
Why: The signature proves the provider sent it and it was not altered, so attackers cannot fake a payment success.
7Authorisation without capture…Very often asked
Why: Authorisations expire after days.
8Which failures should be retried automatically?Very often asked
Why: Hard declines need the customer.
9How should amounts be stored for multiple currencies?Very often asked
Why: Never mix currencies in a sum.
10What does 3-D Secure shift?Very often asked
Why: Strong customer authentication.
11What should happen to webhooks that arrive out of order?Very often asked
Why: State machines reject invalid transitions.
12Which process catches missed webhooks?Very often asked
Why: Compare records regularly.
13In a double-entry ledger, each transaction's entries must…Very often asked
Why: Balanced entries make every movement traceable.
14A payment whose provider call timed out should be marked…Very often asked
Why: It may have succeeded, so retrying blindly risks a double charge.
15What does reconciliation compare?Often asked
Why: It finds payments that one side has and the other does not, or with different amounts.
16What do dunning schedules handle?Often asked
Why: With grace periods for customers.
17Card-testing attacks are reduced by…Often asked
Why: Attackers try many cards quickly.
18What must be collected to submit a chargeback dispute?Often asked
Why: Submit before the deadline.
19Why isolate payment code as a service?Often asked
Why: Change control matters.
20What should never appear in payment logs?Often asked
Why: Logs must not hold card data.
21How do you test declines?Often asked
Why: Test mode simulates outcomes.
22Marketplace sellers are paid…Often asked
Why: The ledger tracks each share.
23UPI payments differ from cards because they…Often asked
Why: Status checks handle pending states.
24How are mistakes corrected in an append-only ledger?Often asked
Why: History stays intact and auditable.
25What does daily reconciliation compare?Often asked
Why: Mismatches reveal missed webhooks and fee errors.
26Tax on an old invoice after a rate change should be…Often asked
Why: Invoices are legal records of what was charged.
27What does a payment processor do?Sometimes asked
Why: The gateway collects details.
28Which metric shows issuer problems quickly?Sometimes asked
Why: Alert on sudden drops.
29While a payment is pending, the UI should…Sometimes asked
Why: Double payments come from retries.
30Partial refunds must be tracked against…Sometimes asked
Why: Never refund more than captured.
31Stored payment methods for subscriptions need…Sometimes asked
Why: CVV must never be stored.
32For a foreign-currency checkout, you should store…Sometimes asked
Why: Refunds and accounting need the original figures.
Track your progress through every blueprint in your dashboard.
Start learning