Payment Gateway (Stripe-like)#
Problem statement (interviewer prompt)
Design a Stripe-style payment gateway: merchants integrate a checkout SDK, you authorise + capture cards, route to the right acquirer/network, run real-time fraud scoring, expose webhooks for events, and maintain a double-entry ledger that reconciles daily.
flowchart LR
M[Merchant]
GW[Payment API]
TOK[Tokenization]
AUTH[Authorization]
PSP[Acquirer / Network]
ISS[Issuer Bank]
REC([Reconciliation])
M --> GW --> AUTH --> PSP --> ISS
GW --> TOK
GW --> REC
classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
class M,GW,TOK,AUTH,PSP,ISS service;
class REC compute;
flowchart TB
subgraph Merchant
CHK([Checkout JS / SDK])
SRV[Merchant server]
end
subgraph Edge
CDN
GW[Payments API gateway]
WAF
IDEM[Idempotency layer]
end
subgraph Core
INTENT[PaymentIntent service]
METHOD[PaymentMethod service]
TOK[Tokenization Vault<br/>PCI scope]
AUTH[Authorization service]
CAP[Capture / settle]
REFUND[Refund]
DISP[Dispute / chargeback]
SUB[Subscriptions / billing]
end
subgraph Networks[Acquirer / Networks]
ACQ[Acquiring bank]
NET[Visa / MC / Amex network]
ISS[Issuer bank]
THREE[3DS / SCA]
AFT[ACH / SEPA / RTP]
ALT[Alt methods<br/>UPI / Wallets / BNPL]
end
subgraph Risk
RISK[Risk engine ML]
RULES[Rule engine]
REV[Manual review]
BLOCK[Blocklists]
end
subgraph Ledger[Ledger & Reconciliation]
LED[(Double-entry ledger)]
RECONC([Reconciliation])
REPORT[Reports / 1099]
end
subgraph Payout
BAL[Balance service]
PAYOUT[Payout service]
end
subgraph WHK[Webhooks Out]
WHKQ[[Outbound queue]]
DEL[Delivery + retry]
DLQ[(DLQ)]
end
subgraph Compliance
PCI[PCI DSS network seg]
KMS[KMS / HSM keys]
AUDIT[Audit log]
KYC[KYC / AML / OFAC]
end
CHK --> GW
SRV --> GW
GW --> IDEM --> Core
Core --> Networks
Networks --> ISS
ISS -. authorize .-> Networks --> Core
Risk -. score .-> AUTH
AUTH --> LED
CAP --> LED
REFUND --> LED
LED --> RECONC --> Payout
Core --> WHKQ --> DEL --> SRV
DEL --> DLQ
Compliance --- TOK
Compliance --- LED
classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
class CHK client;
class GW edge;
class SRV,IDEM,INTENT,METHOD,TOK,AUTH,CAP,REFUND,DISP,SUB,ACQ,NET,ISS,THREE,AFT,ALT,RISK,RULES,REV,BLOCK,REPORT,BAL,PAYOUT,DEL,PCI,KMS,KYC service;
class LED,DLQ datastore;
class WHKQ queue;
class RECONC compute;
class AUDIT obs;
Authorization flow (card)#
- Merchant collects card → tokenizes via vault → token returned.
- Merchant calls
POST /payment_intentswith token + amount + idempotency key. - Risk score; if pass → submit to acquirer.
- Acquirer routes to network → issuer authorizes (hold).
- Later,
capture(settle) → funds move. - Webhooks fire to merchant at each state.
Ledger#
- Double-entry: every event credits one account, debits another.
- Append-only; balances are projections / materialized views.
- Reconciliation periodically reconciles internal vs acquirer statements.
Risk#
- Real-time ML + rules combine velocity, BIN, geo, device fingerprint, blocklists.
- Strong Customer Authentication (3DS) triggered on suspicion / regulatory.
Webhooks#
- At-least-once; signed body; idempotent on merchant side.
- Retries with backoff up to days; DLQ + manual replay.
Glossary & fundamentals#
Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.
| Tag | Concept | What it is | Page |
|---|---|---|---|
HLD |
CDN | edge caching for static assets | cdn |
HLD |
API gateway / BFF | single ingress, auth, rate limit, routing | api-gateway |
HLD |
Pub/Sub & message brokers | topics, consumer groups, delivery semantics | pub-sub-pattern |
HLD |
CAP / PACELC | C vs A under partition; L vs C otherwise | cap-pacelc |
HLD |
Idempotency & retries | safe re-execution, backoff + jitter | idempotency-retries |
LLD |
REST API design | verbs, statuses, pagination, errors | rest-api-design |
Quick reference#
Functional#
- Accept payments (cards, wallets, bank, BNPL, UPI, ACH).
- Tokenize sensitive card data.
- Authorize, capture, refund, dispute.
- Subscriptions / recurring billing.
- Webhooks to merchants.
- Reports & payouts.
Non-functional#
- p99 authorize < 1 s; capture < 2 s.
- Strict financial correctness (no double charge, no lost capture).
- 99.99% gateway availability; PCI-DSS scope.
Capacity#
- 1B+ txns/yr for big providers.
- Peak ~1k txn/s globally; bursts 10k+.
API#
POST /v1/payment_intents (Idempotency-Key required)
POST /v1/payment_intents/{id}/confirm
POST /v1/refunds
POST /v1/webhooks_secrets
Schema#
payment_intents(id, amount, currency, status, idem_key, version)charges(id, intent_id, network_ref, status, ts)ledger_entries(id, account_id, debit, credit, ref, ts)immutablewebhook_events(id, intent_id, status, signature, delivered, attempts)
Trade-offs#
- Strict idempotency keys non-negotiable.
- Append-only ledger simpler audit; reconciliation rebuilds balances.
- Network reliability: many small failures; design assumes 5xx is normal.
- PCI scope minimization: tokenize early, never touch PANs in app services.
Refs#
- Stripe API guide; "Online Migrations at Stripe".
- "Sagas" (Garcia-Molina '87).
- Square / Adyen / PayPal architecture talks.
- ByteByteGo "Design payment system", Alex Xu Vol 2.
FAQ#
How does a payment gateway work?#
A payment gateway tokenizes card data, sends authorization requests through acquirers and card networks to the issuer bank, and confirms funds via webhooks back to the merchant.
What is PCI DSS and why does a payment gateway need it?#
PCI DSS is the Payment Card Industry security standard. Gateways must isolate card data in a tokenization vault to minimize PCI scope and protect cardholders from breaches.
Why do payment gateways use idempotency keys?#
Idempotency keys prevent double charges when clients retry due to network failures. The gateway returns the same response for repeated requests using the same key.
What is the difference between authorization and capture?#
Authorization places a hold on the cardholder's funds. Capture actually moves the money to the merchant. They can happen instantly or be separated by days for delayed billing.
How does a payment gateway prevent fraud in real time?#
Gateways combine ML risk scoring with rule engines using signals like device fingerprint, BIN, velocity, and geolocation, then trigger 3DS challenges for suspicious transactions.
Why do gateways use double-entry ledgers?#
Double-entry ledgers make every money movement auditable and reconcilable. Balances become projections of immutable journal entries, so errors can be traced and replayed.
Further reading#
Curated, high-credibility sources for going deeper on this topic.
- ✍️ Blog - Stripe - Online migrations at scale
- ✍️ Blog - Stripe - Idempotent requests
- ✍️ Blog - Stripe - Rate limiters
- 📑 Docs - PCI DSS v4.0 standard