Design UPI Payment System
Design a UPI-like payment system with real-time payment flows, idempotency, settlement, and fraud detection. Covers NPCI architecture patterns.
Quick answer: Design UPI Payment System
Design UPI Payment System is covered here as a practical system design interview problem. Design a UPI-like payment system with real-time payment flows, idempotency, settlement, and fraud detection. Covers NPCI architecture patterns. Use it to practice requirements, APIs, storage choices, scaling bottlenecks, data consistency, observability, and failure handling for a easy interview round.
Focus on the problem being solved, the main design choice, the failure mode, and the tradeoff you would defend in front of a senior engineer. This page is part of the DosiBridge system design knowledge graph, so it links related concepts, interview problems, tradeoffs, and references instead of leaving the topic isolated.
Problem Statement
Design a Unified Payments Interface (UPI) system that enables instant bank-to-bank transfers using a virtual payment address (VPA). The system must process payments in real time, guarantee exactly-once execution through idempotency, handle settlement between banks, and detect fraudulent transactions -- all at the scale of billions of transactions per month.
Requirements
Functional
- Register VPA (e.g., user@bank) mapped to bank account
- Send money: payer initiates transfer to a payee VPA, debiting payer's bank and crediting payee's bank
- Collect request: payee requests money from payer (payer must approve)
- Transaction history with status tracking (pending, success, failed)
Non-Functional
- Latency: End-to-end payment <5 seconds including bank round-trips
- Consistency: Exactly-once execution -- no double debits, no lost credits
- Availability: 99.95% -- failed payments must auto-reverse within 24 hours
- Scale: 10B transactions/month, 50K TPS at peak
Core Architecture
-
Payment Switch (NPCI-equivalent) -- Central routing layer that resolves payee VPA to the payee's bank, routes the debit request to the payer's bank and the credit request to the payee's bank. Uses a two-phase protocol: debit-first, then credit. If credit fails, initiates auto-reversal of the debit.
-
Idempotency Engine -- Every transaction carries a unique idempotency key (client-generated UUID). The engine stores key-to-outcome mappings in a fast lookup store. Duplicate requests return the cached outcome without re-executing. Keys expire after 24 hours.
-
Settlement Service -- Banks do not move actual money per transaction. Instead, the settlement service aggregates net positions between banks every 15 minutes and settles via a central clearing account. Generates settlement files in ISO 20022 format.
- Fraud Detection Pipeline -- Real-time scoring engine that evaluates each transaction against velocity rules (e.g., >5 transactions in 1 minute), amount thresholds, device fingerprint changes, and ML-based anomaly scores. High-risk transactions are held for step-up authentication (PIN re-entry).
Database Choice
PostgreSQL for the VPA registry and transaction ledger. The ledger table is append-only with columns: txn_id, payer_vpa, payee_vpa, amount, status, created_at, updated_at. Status transitions (INITIATED -> DEBIT_SUCCESS -> CREDIT_SUCCESS or REVERSED) are serialized via row-level locks on txn_id. Redis for idempotency key lookup (SET NX with 24h TTL) and rate limiting. Kafka for the event bus between payment switch, banks, and settlement.
Key API Endpoints
POST /api/v1/pay
-> Body: \{ payer_vpa: "alice@bank1", payee_vpa: "bob@bank2", amount: 500.00, idempotency_key: "uuid-123" \}
-> Returns: \{ txn_id: "TXN-789", status: "INITIATED" \}
GET /api/v1/transactions/\{txn_id\}
-> Returns: \{ txn_id: "TXN-789", status: "SUCCESS", amount: 500.00, timestamp: "..." \}
POST /api/v1/collect
-> Body: \{ requester_vpa: "bob@bank2", payer_vpa: "alice@bank1", amount: 200.00, note: "Dinner split" \}
Scaling Insight
The debit-first, credit-second pattern with auto-reversal is the key reliability mechanism. By always debiting first, the system ensures money is never created out of thin air. If the credit leg fails (payee bank down), a reversal job re-credits the payer within minutes. This two-phase approach avoids the complexity of distributed transactions across banks while maintaining financial integrity.
Key Tradeoffs
| Decision | Option A | Option B | Chosen |
|---|---|---|---|
| Transaction model | Synchronous 2PC across banks | Debit-first with async reversal | Debit-first -- banks are independent systems, 2PC is impractical across org boundaries |
| Settlement | Real-time gross (per txn) | Net settlement (batched) | Net settlement -- 1000x fewer inter-bank transfers, lower cost |
| Fraud detection | Pre-transaction blocking | Post-transaction flagging | Pre-transaction -- prevents fraud rather than chasing refunds, slight latency cost acceptable |
Original DosiBridge notes for Design UPI Payment System
This section is written specifically for this page, not copied from a general system-design checklist. The useful way to study Design UPI Payment System is to connect the concept to a production service where growth exposes the first weak assumption in the original design. That framing changes the design discussion from definitions to operating choices.
What makes this topic distinct
- Core Entity: For Design UPI Payment System, decide the core entity before choosing tools; otherwise the design looks clean but fails when design changes.
- Read/Write Path: For Design UPI Payment System, decide the read/write path before choosing tools; otherwise the design looks clean but fails when upi changes.
- Contention Point: For Design UPI Payment System, decide the contention point before choosing tools; otherwise the design looks clean but fails when design changes.
- Abuse Path: For Design UPI Payment System, decide the abuse path before choosing tools; otherwise the design looks clean but fails when upi changes.
- Recovery Workflow: For Design UPI Payment System, decide the recovery workflow before choosing tools; otherwise the design looks clean but fails when design changes.
Distinct angle: UPI-style transfers optimize for trust and reconciliation
A UPI-like payment rail should be designed around irreversible user trust moments: debit, credit, confirmation, reversal, and dispute. The architecture needs idempotency keys, bank/provider callbacks, ledger entries, and reconciliation jobs. The system is not just a wallet UI; it is a correctness-first workflow where duplicate success messages are worse than a slow pending state.
Design UPI Payment System correctness boundary
For this problem, separate the user-visible action from background work. The correctness boundary is the smallest state transition that must not be duplicated, lost, or reordered. Naming that boundary makes the solution more original than a stock API/database/cache template.
Design UPI Payment System scaling bottleneck
The first bottleneck should be described in the language of this system: a hot timeline, a contested seat, a busy wallet ledger, a media-processing queue, or a search index update delay. That bottleneck decides which component deserves the deepest interview discussion.
Production review question
If Design UPI Payment System suddenly receives 10x traffic, which entity becomes contested first, and what queue, lock, shard, or cache protects that entity without hiding correctness bugs?
Practical metric to track
Track design-upi health as a named dashboard or review item: combine one user-facing metric, one saturation metric, and one correctness metric. For Design UPI Payment System, this keeps the discussion grounded in behavior that can be measured after deployment instead of generic advice that sounds good in an interview but never gets verified.