System Design Problems interview question · Most asked
Design a payment system.
Summary
Accept payment intents with idempotency keys, orchestrate charges through payment providers with a state machine, record every money movement in a double-entry ledger, process provider webhooks reliably, and reconcile daily against provider reports.
Requirements
- Charge customers, refunds, payouts to merchants
- No double charges, no lost payments
- Auditability and reconciliation
- PCI-DSS compliance; high correctness over raw throughput
API
POST /api/payments Idempotency-Key: <uuid>
{"amount": 4999, "currency": "USD", "customer_id": "c1", "payment_method": "pm_..."}
→ 201 {"id": "pay_123", "status": "processing"}
POST /api/payments/{id}/refunds {"amount": 1000}
POST /webhooks/provider (signed)
Data Model
payments(id, idempotency_key UNIQUE, amount_minor bigint, currency, status, provider_ref, created_at)
payment_events(id, payment_id, from_status, to_status, data, created_at) -- append-only
ledger_entries(id, txn_id, account_id, amount_minor, direction /* debit|credit */, created_at)
-- invariant: sum(debits) = sum(credits) per txn_id
Architecture
The payment API stores the intent with its idempotency key in one transaction, then the payment orchestrator calls the provider (tokenized card data only, via provider SDKs, so card numbers never touch your servers). State transitions are persisted and published via an outbox. Provider webhooks are verified, deduplicated and applied to the state machine. A ledger service records double-entry transactions; a reconciliation job compares ledger, payments and provider settlement files.
Deep Dives
- Idempotency: replaying a request with the same key returns the original result
- Unknown outcomes: on timeouts, query the provider by your reference before retrying
- Money types: integers in minor units with currency, never floats
- State machine: created → processing → succeeded/failed → refunded (partial)
- Security: tokenization keeps you in a lighter PCI scope
Scaling
- Correctness first: strongly consistent relational DB
- Partition by merchant for large scale
- Async processing for payouts and reconciliation
Comparison / Tradeoffs
| Decision | Option chosen | Alternative | Why |
|---|---|---|---|
| Consistency | Strong (ACID) | Eventual | Money requires correctness |
| Record keeping | Double-entry ledger | Balance columns | Auditability, invariants |
| Card data | Provider tokenization | Store PANs | PCI scope and risk |
Explanation
What interviewers look for
A structured approach: clarify requirements and scale, sketch the API and data model, draw the high-level architecture, then go deep on the hardest component and discuss trade-offs, bottlenecks and failure modes.
Follow-up questions
- How do you handle currency conversion?
- How do you detect fraud?
- What if the webhook arrives before your API call returns?
More most-asked System Design Problems questions
- Design a URL shortener (like bit.ly).
- Design a distributed rate limiter.
- Design a chat application (like WhatsApp or Slack).
- Design a social media news feed (like Twitter/X or Instagram).
- Design a notification system (email, SMS, push).
- Design a ticket booking system (like Ticketmaster).
- Design a distributed unique ID generator.
- Design a webhook delivery system.