About Us Contact Us Write for Us Advertise
Home > System Design > High-Level Design > Design a Payment System (Stripe) — System Design
System Design › High-Level Design

Design a Payment System (Stripe) — System Design

Design a payment system where correctness is everything: idempotency keys to prevent double charges, the PSP flow and webhooks, an immutable double-entry ledger, strong consistency, reconciliation, and PCI tokenization.

Shiv Pandey
Shiv Pandey
Oct 13, 2026 | 85 views
Design a Payment System (Stripe) — System Design

🔴 High-Level Design · Super-senior · correctness over everything

"Design a payment system" (like Stripe, or the checkout/payments service inside an e-commerce company). This one is different from every other design question: it's not about raw scale — it's about correctness. Money can't be lost, can't be double-charged, and every cent must be accounted for. That obsession with consistency, idempotency, and ledgers is exactly what interviewers probe. Let's design it carefully.

The whole design in one line: accept a payment request, guarantee it's processed exactly once using an idempotency key, hand off to an external payment provider, and record every money movement in an immutable double-entry ledger you can reconcile.

Step 1 — Requirements

  • Functional: charge a customer; handle success/failure; support refunds; integrate with external payment providers (Stripe, banks, card networks); keep an accurate record of all transactions.
  • Non-functional (the priorities are unusual): correctness & consistency above all — never double-charge, never lose money; strong auditability; secure (handling card data); and reliable under failures. Raw throughput matters, but never at the cost of a wrong balance.

Step 2 — The #1 rule: idempotency (no double charge)

🔴 Networks are unreliable. A user clicks "Pay," the request succeeds, but the response is lost — so the client retries, and now you risk charging them twice. The defence is an idempotency key: the client generates a unique key per payment attempt and sends it with the request. The server records "I've processed key X." If the same key arrives again, it returns the original result instead of charging again. This single mechanism is the most important thing in a payment system — and the first thing to say.

POST /payments  { idempotency_key, amount, ... }
  if key already processed → return the SAME result (no new charge)
  else → process once, store result under the key

Step 3 — The payment flow

Client Payment Svc(idempotency) PSP / Stripecard networks Ledger(double-entry) Webhook →update status

The Payment Service validates and dedupes (idempotency), then calls a Payment Service Provider (PSP) like Stripe — you never touch card networks directly. The PSP processes the actual charge and returns success/failure, often asynchronously via a webhook (payments can take seconds and go through multiple states: pending → authorized → captured). You update the payment's status from that webhook, and record the money movement in the ledger.

Step 4 — The double-entry ledger

🔴 Money isn't tracked as a single "balance" you increment — that's fragile and unauditable. Instead, use a double-entry ledger (the centuries-old accounting method): every transaction is recorded as balanced entries — a debit from one account and a matching credit to another, always summing to zero. This makes the system auditable (you can trace every cent), correct by construction (books must balance), and append-only (you never edit an entry; a correction is a new reversing entry). Naming "immutable double-entry ledger" signals you understand financial systems, not just CRUD.

Step 5 — Consistency & reconciliation

🔴 Two more correctness pillars:

  • Strong consistency for money: unlike likes or feeds, balances and ledger writes need ACID transactions — you do not use eventual consistency for account balances. A relational DB with real transactions is the right home for the ledger.
  • Reconciliation: your records and the PSP's records can drift (a webhook was missed, a timeout left a payment in limbo). A periodic reconciliation job compares your ledger against the provider's settlement reports and flags/fixes discrepancies. Every serious payment system has this safety net.

Step 6 — Handling the tricky failure states

🔴 The nightmare case: you call the PSP, it times out — did the charge go through or not? You must not assume. Options: query the PSP for the status by your idempotency key, or leave the payment pending and let reconciliation/retry resolve it. The rule is never guess about money — verify. Combine this with idempotent retries so a safe retry can't double-charge.

Step 7 — Security

🟠 Card data is radioactive. You never store raw card numbers — that's PCI-DSS territory. Instead, the card is tokenized by the PSP: you store a token that represents the card, and the real number lives with Stripe/the provider. This shrinks your compliance scope and risk enormously.

The interview-ready walkthrough

"Payments are about correctness, so I lead with idempotency keys to guarantee exactly-once and no double charges. The Payment Service hands off to a PSP like Stripe (never touching card networks directly), updating status from its webhooks since charges are async. Every money movement goes into an immutable double-entry ledger for auditability, stored with ACID/strong consistency — no eventual consistency for balances. I add a reconciliation job to catch drift with the provider, never guess on timeouts (verify by idempotency key), and tokenize cards for PCI compliance." That reframes the whole question around correctness — which is exactly what it's testing."

What to read next

← Design Uber · Design Dropbox →

Related Articles

Design Ticketmaster / BookMyShow — System Design
System Design › High-Level Design

Design Ticketmaster / BookMyShow — System Design

Design Dropbox / Google Drive (File Sync) — System Design
System Design › High-Level Design

Design Dropbox / Google Drive (File Sync) — System Design

Design Uber / Lyft (Ride-Hailing) — System Design
System Design › High-Level Design

Design Uber / Lyft (Ride-Hailing) — System Design

Design YouTube / Netflix (Video Streaming) — System Design
System Design › High-Level Design

Design YouTube / Netflix (Video Streaming) — System Design