Design problems
Payments & fintechHardSDE-3 40 min

Design a payment gateway for merchants (Razorpay)

Asked at
AmazonCREDPaytmPhonePeRazorpayStripe

The interviewer asks

“Design a payment gateway like Razorpay that lets Indian merchants accept UPI, cards, netbanking and wallets through one checkout and one API. Focus on routing payments to banks and networks with the best success rate, settling money to merchants, and telling merchants reliably what happened.”

What a strong answer looks like

A strong answer frames the gateway as a multi-tenant layer between thousands of merchants and many banks, networks and NPCI. The merchant creates an order, the hosted checkout collects the method, and the payment service runs a per-payment state machine (created → authorized → captured, or failed) through method-specific adapters: card acquirers via the networks, UPI via a PSP bank and NPCI, netbanking via bank redirects. The India-specific heart is smart routing: the same card or UPI payment can go through several acquiring banks or PSPs, and success rates change minute to minute, so a router chooses the terminal using live success-rate and latency data, with health-based failover. Around this: card tokenisation as required by RBI (no storing of raw card numbers by merchants), a ledger and settlement engine that pays merchants T+1/T+2 from the nodal/escrow account after fees and GST, reliable signed webhooks, and reconciliation with every bank's MIS files. Deep dives: smart routing, late success and reconciliation, settlements, and multi-tenant isolation during festive peaks.

Concepts to mention

orders and payment attempts state machinesmart routing by live success rateterminals across acquirers / PSPscard network tokenisation (RBI rules)pending / late success handlingreconciliation with bank MIS filesnodal / escrow account and settlement T+2double-entry ledger with fees and GSTsigned at-least-once webhooksper-merchant rate limits and cell isolation

1 Requirements

Functional

  • Merchant onboarding with API keys; merchants create orders and receive payments via hosted checkout, SDKs or S2S APIs.
  • Support UPI (intent, collect, QR), cards (debit/credit, with 3DS/OTP), netbanking, wallets, EMI and pay-later.
  • Route each payment to an acquirer/PSP terminal chosen for success rate, cost and health.
  • Auto or manual capture, refunds (full and partial), and payment status APIs.
  • Signed webhooks for payment, refund and settlement events.
  • Settle collected money to merchants (default T+2, instant for a fee) after fees and taxes.
  • Dashboards and reports; reconciliation with bank and network files.
  • Save cards for repeat customers via network tokens.

Non-functional

  • Gateway-added latency under 150 ms p99; total payment time dominated by bank/NPCI and user action.
  • 99.99% availability; one failing bank must not affect payments routed elsewhere.
  • Success rate is a product metric: routing should lift it by measurable points.
  • Peak 20k payments/s during festive sales and big events, with large single merchants.
  • Money is never lost: every payment reaches a final state and is reconciled within T+1.
  • PCI DSS compliance for card data; RBI tokenisation rules; Indian payment data stored in India.

Out of scope (say it out loud)

  • Merchant KYC and risk underwriting details.
  • Building the UPI app (covered by the UPI design).
  • Lending products like merchant cash advance.

2 Estimates

Payments~30M/day ≈ 350/s avg, 20k/s peak30M ÷ 86,400 ≈ 350/s; sale-hour peaks are spiky (flash sales, IPL ticket drops), ~50x average for minutes.
Method mix~70% UPI, ~20% cards, ~10% othersUPI dominates Indian online payments by count; cards dominate by value for some merchants.
Merchants~10M registered, ~1M activeLong tail of small merchants plus a few very large ones.
Routing decisionsone per payment attempt, <5 msDecision uses in-memory success-rate stats per (method, issuer/bank, terminal).
Webhooks~100M/day~3 events per payment + refunds + settlements.
Settlement batches~1M merchant payouts/dayEach active merchant settled daily (T+2 cycle rolls).
Recon file lines~50M/dayEvery payment appears in one or more bank/network MIS files.

3 API

EndpointWhat it does
POST/v1/ordersMerchant creates an order {amount, currency, receipt}; idempotent on receipt or Idempotency-Key.
POST/v1/payments/createCheckout submits the method details {order_id, method, vpa|card_token|bank}; returns next action (redirect, UPI intent, OTP).
POST/v1/payments/{id}/captureCapture an authorised payment (manual capture merchants).
POST/v1/payments/{id}/refundRefund {amount}; idempotent.
GET/v1/payments/{id}Status for merchants that poll after a webhook delay.
POST/callbacks/{bank}Bank/PSP/network callbacks with the result; verified by signature or checksum.
GET/v1/settlements?from=&to=Settlement batches with linked payments, fees and taxes.

4 Data model

orders / paymentsPostgres/MySQL sharded by merchant_id
order_idmerchant_idamount_paisestatus; payment_idorder_idmethodterminal_idgateway_refbank_ref (RRN/UTR)statuserror_codeversion

One order may have several payment attempts. Payment state transitions are conditional updates with an outbox.

terminalsPostgres + in-memory config
terminal_idacquirer/PSPmethods supportedMDR costlimitsmerchant categoriesstatus

A terminal is a merchant ID at an acquiring bank or PSP. Routing chooses among eligible terminals.

routing_statsRedis / in-memory sliding windows (fed by Flink)
(method, issuer or bank, terminal) → attemptssuccessesp95 latencyerror codes over last 1530 min

Fresh signal for routing; Flink aggregates payment outcome events.

token_vaultPCI zone, HSM-encrypted
network token referencecard fingerprintlast4networkexpiry

RBI rules: merchants and gateways do not store full card numbers; network tokens (Visa/Mastercard/RuPay) are stored instead.

ledgerPostgres, append-only double-entry
journal_idaccount (merchant balance, fees, GST payable, nodal account, refunds)debitcreditpayment_id

Source for settlement amounts; must reconcile with the nodal/escrow bank statement daily.

settlementsPostgres
settlement_idmerchant_idperiodgrossfeestaxrefundsnetutrstatus

Created by batch; UTR from bank on payout completion.

webhook_deliveriesPostgres / Kafka
event_idmerchant_idurlattemptsnext_attempt_atlast_status

At-least-once delivery with exponential backoff for up to 24 h.

5 Architecture

CLIENTSEDGESERVICESASYNCDATAEXTERNALcreate orderpaypick terminallive SRcard tokencallbacksstate + outboxoutbox relayoutcomessigned webhookspayouts, reconCheckout / SDKMerchant serverEdge + API gatewayBank / NPCI adaptersPayment serviceSmart routerToken vault (PCI)Kafka (paymentevents)Flink success-ratestatsLedger + settlementjobsWebhook dispatcherPayments DB (sharded)Redis (routing stats)Acquirers, NPCI,networksNodal / escrow bank
ClientEdge / gatewayService / workerQueue / streamCacheDatabase / storageAI / modelThird partyrequestasync (event / queue)

Hover a box to highlight its connections.

6 Request flows

Card payment with smart routing

  1. 1Merchant server creates an order for ₹2,499; checkout opens and the customer picks a saved card (network token).
  2. 2Payment service creates a payment attempt and asks the router for a terminal.
  3. 3Router filters terminals eligible for this merchant, card network and card type (e.g. a RuPay debit card from Bank X), then scores them by last-5-minute success rate for this issuer, latency and MDR cost; it picks Acquirer B because Acquirer A's success rate for Bank X dropped from 92% to 70%.
  4. 4Adapter sends the auth request through the acquirer; the issuer requires OTP, so the customer is redirected to the bank's 3DS/OTP page.
  5. 5Callback from the acquirer arrives with success; payment moves to authorized and, for auto-capture merchants, to captured, with an outbox event.
  6. 6Merchant gets payment.captured webhook; checkout returns the signed payment ID to the merchant page, which the merchant server verifies with its secret.

UPI intent payment

  1. 1Customer chooses UPI; the router picks a PSP bank based on live UPI success rates.
  2. 2Gateway asks the PSP to create a collect or intent transaction and returns an intent link; the customer's UPI app opens with the amount and merchant VPA.
  3. 3Customer enters UPI PIN in their app; NPCI routes the debit to their bank and credit to the gateway's merchant account at the PSP.
  4. 4PSP sends a callback with status and RRN; if no callback arrives within the expected window, a status poller checks with the PSP within NPCI's allowed limits.
  5. 5Payment becomes captured; webhooks and settlement follow.

Settlement to merchant (T+2)

  1. 1Acquirers and PSPs credit the nodal/escrow account with net amounts; recon matches their MIS files to payments.
  2. 2Settlement job computes per merchant: captured amount - refunds - fees - GST on fees, from the ledger.
  3. 3It creates payouts with idempotent references and calls the bank's payout API (NEFT/RTGS/IMPS); bank returns a UTR.
  4. 4Settlement records the UTR and emits settlement.processed webhooks.

7 Deep dives

Smart routing to maximise success rate

In India, the same payment can often go through several acquiring banks or PSPs, and success rates vary by issuer, card type, method and time of day; a bank's server can degrade for 20 minutes during a sale. A few percentage points of success rate is real revenue for merchants, so routing is a core feature. The router runs in-process on the payment service with config and stats in memory, so a decision takes under 5 ms. Step one: eligibility, from rules (merchant category, method, card network, amount limits, merchant's own acquirer contracts). Step two: scoring, using live success rates per (method, issuer bank, terminal) over sliding windows of 1, 5 and 30 minutes computed by Flink from payment outcome events and pushed to Redis. Blend success rate, latency and cost. Step three: exploration, sending a small share of traffic (a few percent) to non-preferred terminals so the system notices when a degraded terminal recovers, like a multi-armed bandit. Health checks open a circuit on a terminal with error spikes. Be careful to count only failures caused by the bank or network, not user drop-offs or wrong OTPs, otherwise the router punishes healthy terminals. Retry on another terminal is possible only for some failures and only before the customer is charged; never retry when the result is unknown.

Late success, unknown status and reconciliation

Bank and NPCI systems often reply late or not at all. A UPI payment can show failed or pending on our side while the customer's account was debited; a card authorisation can time out after approval. Handle three cases. First, pending/unknown: do not mark failed; poll the bank or PSP status API with backoff and within their rate limits (NPCI limits how often status checks can be made), and keep the checkout showing 'processing' for a while. Second, late success after the order was cancelled or the customer paid again: the payment becomes captured; for merchants with auto-refund settings, a job refunds late successes that were not used, otherwise the merchant is told via webhook. Third, end-of-day truth: every bank and network sends MIS/settlement files. Recon matches each line to a payment by gateway_ref or RRN/ARN and amount, and builds exception queues: debited but failed in our system, success but missing in file, amount mismatch. Most exceptions resolve automatically by moving the payment to the correct state and posting ledger corrections; customers who were debited for a failed payment get auto-refunds within the RBI turnaround time (TAT) framework, which also mandates compensation for delays.

Settlement engine and the ledger

Gateways in India must keep merchant funds in a nodal or escrow account and settle according to RBI's payment aggregator guidelines. The ledger is the source of truth for what each merchant is owed. Every captured payment posts: debit receivable from acquirer, credit merchant balance (gross minus fee), credit fee revenue, credit GST payable. Refunds reverse the merchant part. When an acquirer credits the escrow account, recon moves the money from receivable to escrow cash. Settlement runs per cycle: for each merchant, sum settleable balance (payments captured before the cut-off and already received from acquirers), subtract holds for disputes or risk reserves, and create a payout. Payouts are idempotent by (merchant, cycle) so a re-run never pays twice. Instant settlement is a product on top: pay from the gateway's own working capital before acquirers settle, for a fee, which is credit risk and needs limits. Daily, the escrow bank statement must equal the sum of ledger escrow entries; any difference is a high-severity alert.

Multi-tenancy and festive peaks

A few merchants (a ticketing site during a cricket ticket drop, an e-commerce sale at midnight) can send 50x normal traffic. Protect everyone else. Rate-limit and quota per merchant at the edge with burst allowances agreed in advance; isolate the biggest merchants into dedicated shards or cell pools so a surge does not exhaust shared database connections; use per-bank bulkheads so a slow bank's adapter cannot consume all threads. Pre-scale before known events and run load tests with banks, since bank capacity, not ours, is often the limit; the router can spread load across acquirers to avoid tripping a single bank's limits. Keep checkout static assets on a CDN. Shed non-critical work first under pressure: dashboards, reports and analytics consumers can lag; payment creation and callbacks cannot.

8 Trade-offs

Route by live success rate vs fixed priority

Fixed priority lists are easy to reason about and match contract cost, but react slowly to bank outages. Live scoring lifts success rate but needs reliable stats, careful failure classification and exploration traffic. Most gateways combine rules for eligibility and cost with live scoring.

Auto-capture vs manual capture

Auto-capture reduces unclaimed authorisations and is the default for most merchants. Manual capture lets merchants confirm stock first, but uncaptured payments must be auto-refunded after a window, which customers dislike.

Instant settlement vs T+2

Instant settlement improves merchant cash flow but the gateway pays before receiving funds, taking credit and fraud risk. Offer it with limits based on merchant history and refund rates.

Webhooks vs polling for merchants

Webhooks are timely but can be delayed or lost on the merchant side. Provide both: at-least-once signed webhooks with retries and a status API, and tell merchants to verify signatures and handle duplicates.

9 Bottlenecks

A single bank's capacity

During a sale, one issuer or acquirer hits its TPS limit and starts timing out. The router spreads traffic, circuit-breaks the degraded terminal and uses exploration to detect recovery.

Hot merchant shard

One giant merchant overwhelms a shard. Move large merchants to dedicated cells, and partition their payments by payment_id within the cell.

Recon at month-end and after big sales

File sizes jump 10x. Run recon in Spark over S3 files partitioned by bank and date, and match with hash joins rather than per-row DB lookups.

10 Failure handling

Bank callback never arrives

The payment stays pending; status pollers query the bank with backoff. End-of-day MIS files settle the final state. Customers debited for failed payments get auto-refunds within TAT.

Webhook endpoint of a merchant is down

Deliveries retry with exponential backoff for up to 24 hours; after that the merchant is alerted and can fetch events via API. Other merchants are unaffected because each merchant has its own delivery queue.

Router stats pipeline (Flink) stops

Stats go stale; the router detects stale timestamps and falls back to static priority rules with health checks, so payments continue at a slightly lower success rate.

11 What impresses

  • Explains that success rate is the product, and designs routing with live stats, exploration and failure classification.
  • Handles UPI and card late successes with pollers, recon and auto-refunds within RBI TAT.
  • Knows merchants cannot store raw card numbers in India and uses network tokens.
  • Describes settlement from an escrow account with fees, GST, reserves and idempotent payouts.
  • Isolates huge merchants into cells and uses per-bank bulkheads.
  • Says never to retry on another terminal when the first outcome is unknown.

12 Mistakes

  • Designing a single-processor flow and ignoring routing across banks.
  • Marking a payment failed on timeout, leading to double debits.
  • Retrying an unknown card authorisation on a second acquirer.
  • Settling merchants from payment status without a ledger and reconciliation.
  • Storing raw card numbers outside a PCI vault.
  • Letting one merchant's spike take down shared infrastructure.

13 Follow-ups

Q1How do you measure success rate fairly when users abandon OTP pages?
Q2How would you add recurring payments (UPI AutoPay, card mandates)?
Q3How do you handle disputes and chargebacks for cards?
Q4How would you design the checkout to work well on slow networks?
Q5What changes if the RBI requires all payment data to stay in India and you run multi-region?
Q6How would you offer a 'payment links' product on top of this?

Practice questions

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free