System Design: Payment Gateway (Stripe / Razorpay: Idempotency, Card Vault, UPI, Ledger, Settlement)
Goal: Design Walnut Pay, our own payment gateway, like Stripe or Razorpay. Merchants call one API. We talk to banks, card networks and NPCI, and handle about 50 million payment attempts a day.
We hold the merchants' money for a day or two, then pay it out. No customer pays twice for one order, and no rupee or cent goes missing. If a slow bank lets a second debit through, we refund it automatically.
1. What We Are Building
๐ Premium section
2. Requirements and Scale
2.1 What the System Must Do
- FR-01 Sign up and get API keys. Pass identity checks (called KYC, "know your customer"), then get test keys at once and live keys after review.
- FR-02 Take a payment. Create a payment, confirm it with a card or UPI, and read its status.
- FR-03 Reserve now, charge later. For cards, approve now (an authorization) and take the money later (a capture), here when the tent ships.
- FR-04 Run the bank's identity check. 3-D Secure, where the bank may ask Jake to confirm it's him, and India's two-factor rules (section 8).
- FR-05 Save a card. Jake can pay next time without typing his card, and Emma never sees the card number.
- FR-06 Refund. In full or in part.
- FR-07 Get told about changes. A signed webhook for every state change (section 15).
- FR-08 Get paid. Money reaches the merchant's bank account on a schedule, with reports (section 12).
- FR-09 Handle disputes. See chargebacks and upload evidence (section 13).
- FR-10 Check every payment for fraud before it goes to a bank (section 14).
- FR-11 Route across several acquirers and banks, so one bad acquirer can't fail a large share of payments (section 10).
- FR-12 Dashboard and reports. A lower priority (P1) than the rest.
2.2 How Well It Must Do It
NFR-01 Never keep two charges for one payment, and never lose a payment we said yes to. If a late bank answer makes a second debit, we refund it automatically (section 6.6).
NFR-02 The ledger always balances. Every record of money moving has lines that add up to zero (section 11).
NFR-03 The payment API is up 99.99% of each month. That is about 4.3 minutes of downtime.
NFR-04 We add less than 300 ms at p99 to a confirm call. p99 means 99 out of 100 calls are faster. The bank's time comes on top.
NFR-05 We carry 3,000 attempts a second at peak, and design for 6,000 (section 2.3).
NFR-06 We meet the card security standard, PCI DSS, at Level 1. PCI DSS is the card industry's rule book for anyone who handles card numbers. Mastercard (2026) puts every merchant payment gateway at Level 1, the strictest, at any volume (section 8).
NFR-07 Indian payment data stays in India. The Reserve Bank of India (RBI), India's central bank, made this a rule on 6 April 2018 (section 20).
NFR-08 Every payment reaches a final, known state within 5 days, checked against bank files. RBI has a rule from 2019 for UPI merchant payments. If the customer was debited but the merchant's bank never confirmed the money, the bank must reverse it by T+5, five calendar days after the payment day. We match that.
NFR-09 Webhooks arrive at least once, within 3 days (section 15).
NFR-10 We check every money movement against the banks every day. This is called reconciliation, and we do it one day later, at T+1 (section 12).
2.3 The Numbers
These are round numbers we chose. We count payment attempts. An attempt is one try to pay with one method. If Megan's UPI app fails and she tries a card, that's two attempts for one payment.
| Item | Value | How we got it |
|---|---|---|
| Attempts per day | 50 million | Our choice for a large gateway |
| Mix | UPI 55%, cards 35%, net banking (the customer pays on their bank's own site) and wallets 10% | Strong in India, cards worldwide |
| Average rate | about 580 a second | 50 million / 86,400 seconds |
| Peak | about 3,000 a second | 5 times the average, a festival sale hour |
| Design target | 6,000 a second | 2 times the peak |
| Peak by method | cards about 1,050, UPI about 1,650 a second | 35% and 55% of 3,000 |
| Successful payments | about 40 million a day | about 4 in 5 attempts succeed |
| API requests | about 15,000 a second at peak, design 30,000 | about 5 calls per attempt on average |
| Merchants | 2 million; the biggest sends about 300 attempts a second | 10% of peak; drives the hot account problem: every one of its payments updates the same balance (section 11.5) |
| Webhooks | about 120 million a day, about 7,000 a second at peak | about 3 events per successful payment |
| Ledger lines | about 400 million a day; about 10,000 a second at peak, design 20,000 | about 10 per payment; see below |
| Storage | about 300 GB a day, about 110 TB a year before copies | about 6 KB per attempt |
Is that peak realistic? It's above Stripe's Black Friday peak of 152,000 transactions a minute, about 2,500 a second (2025). UPI makes Indian payment counts very large, with small amounts. Juspay, an Indian payment company, handles 200 million transactions a day (2025), which already average about 2,300 a second.
Bursts can be sharp. Razorpay saw 200 to 1,500 requests a second within seconds in 2021. So we design for twice the peak.
The 5 API calls per attempt count the calls that do work. A card attempt needs 2 to 3. Checkout status polls come on top.
At about 15 polls per UPI attempt (our assumption), that is about 25,000 light reads a second at peak and 50,000 at design. They read a replica (a read-only copy of the database that trails the main one by a moment) and write nothing (section 17.1).
Ledger lines are the rows of our money record (section 11). A payment writes about 10 lines over its life: 2 to 4 at capture, the rest at settlement, release and payout.
At peak only captures are written live. About 2,400 payments a second succeed (4 in 5 of 3,000 attempts). At no more than 4 lines each, that is at most about 10,000 lines a second. Settlement and payout lines arrive in batches at quiet hours.
How long do we keep data online? A cardholder can dispute a payment usually up to 120 days later, and up to 540 days in some cases (Adyen, 2026). So we keep 18 months in the main databases, then move older data to cheaper archive storage for as long as the law requires.
2.4 Out of Scope
- Building a card network or a bank. We connect to them.
- Issuing cards. Jake's bank issues his card, not us.
- Lending.
- Split payments for marketplaces. One payment paid out to several sellers. The ledger could carry it with one
pendingaccount per seller, but we leave it out. - Recurring payments. UPI AutoPay and card e-mandates for subscriptions.
- Tax filing for merchants.
- KYC vendor internals. We call identity-check services. We don't build them.
- Crypto.
3. Who Moves the Money
๐ Premium section
4. The API Merchants See
๐ Premium section
5. High-Level Design
๐ Premium section
6. Deep Dive: Exactly-Once Money Movement
๐ Premium section
7. Deep Dive: Card Payments
๐ Premium section
8. Deep Dive: The Card Vault and 3-D Secure
๐ Premium section
9. Deep Dive: UPI Payments
๐ Premium section
10. Deep Dive: Routing Across Acquirers and Banks
๐ Premium section
11. Deep Dive: The Ledger
๐ Premium section
12. Settlement, Payouts and Reconciliation
๐ Premium section
13. Refunds, Disputes and Chargebacks
๐ Premium section
14. Fraud and Risk in the Payment Path
๐ Premium section
15. Webhooks
๐ Premium section
16. Multi-Tenant Limits
๐ Premium section
17. Capacity
๐ Premium section
18. What Happens When Each Part Goes Down
๐ Premium section
19. Bottlenecks
๐ Premium section
20. Regions and Data Residency
๐ Premium section
21. Security
๐ Premium section
22. Running It
๐ Premium section
23. Trade-offs
๐ Premium section
24. In the Interview
๐ Premium section
25. How We Measured
๐ Premium section
26. Further Reading
๐ Premium section
Explore the Technologies
๐ Premium section