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

← All System Design Problems questions