system-design

Practice Problem: Design a Digital Wallet

Prompt: Design a digital wallet (like a Careem Pay / PayPal / Venmo balance) where users can top up, hold a balance, send money to other users, and withdraw. Attempt it cold for 45 minutes before reading the solution.

Tests: balance correctness under concurrency, idempotent transfers, the ledger model, strong consistency. A close cousin of the payment system.


Solution outline

1. Requirements

2. Estimation

Millions of users, thousands of transfers/sec at peak. Data is small but must be perfectly durable and consistent. The challenge is correctness under concurrency, not raw scale.

3. Core design — a ledger, not a balance field

🚨 Don’t store balance as a mutable number you increment. Use a double-entry, append-only ledger: every transaction is two entries (debit one account, credit another) summing to zero. Balance is derived from (or a cached running total updated atomically with) the ledger entries. This makes correctness checkable and gives a full audit trail.

Transfer $50 A→B:
  A: -50 (debit)   B: +50 (credit)   sum = 0 ✓  (one atomic transaction)

4. Correctness under concurrency

5. Deep dives

6. Trade-offs

| Decision | Chosen | Why | | — | — | — | | Balance | Double-entry ledger | Auditable, checkable, no lost updates | | Transfer | Single ACID transaction + row lock | No double-spend under concurrency | | Retries | Idempotency key | Networks force retries; no double transfer | | Consistency | CP (correctness over availability) | A wrong balance is worse than downtime |

7. What a strong answer includes

The ledger as the correctness foundation, idempotency keys for transfers, atomic balance-check-and-debit to prevent overdraw/double-spend, explicit CP stance, and reconciliation for external top-up/withdrawal. A weak answer stores a mutable balance and updates it without idempotency or atomicity — vulnerable to double-spend and double-processing.


Further reading