Design a Digital Wallet
Design a digital wallet with balance management, P2P transfers, transaction history, and fraud detection.
Quick answer: Design a Digital Wallet
Design a Digital Wallet is covered here as a practical system design interview problem. Design a digital wallet with balance management, P2P transfers, transaction history, and fraud detection. Use it to practice requirements, APIs, storage choices, scaling bottlenecks, data consistency, observability, and failure handling for a medium 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 digital wallet system (like PayPal or Venmo) that allows users to add funds from bank accounts, maintain a wallet balance, send money to other users (P2P transfers), pay merchants, and view transaction history. Must guarantee no money is created or lost, handle concurrent transactions, and detect fraud.
Requirements
Functional
- Add funds to wallet from linked bank account (ACH/bank transfer)
- P2P transfer: send money to another user by email, phone, or username
- Pay merchants via QR code or in-app checkout
- Transaction history with search and filtering (date range, type, amount)
Non-Functional
- Consistency: Zero tolerance for balance discrepancy -- double-entry bookkeeping
- Latency: P2P transfer completes in <2 seconds for wallet-to-wallet
- Scale: 100M users, 50M transactions/day, 5K TPS at peak
- Security: PCI-DSS compliant, all financial data encrypted at rest and in transit
Core Architecture
-
Ledger Service (Double-Entry Bookkeeping) -- Every money movement creates two ledger entries: a debit from one account and a credit to another. For P2P transfer: debit sender's wallet, credit receiver's wallet. Both entries are written atomically in a single database transaction. The sum of all debits always equals the sum of all credits -- enabling audit reconciliation.
-
Balance Service -- Maintains the current balance per wallet as a materialized view of the ledger. Balance = sum(credits) - sum(debits) for the wallet. Cached in Redis for fast reads. On each transaction, the balance is updated atomically with the ledger write using a CHECK constraint: balance >= 0 (prevents overdraft).
-
Payment Gateway Integration -- Handles add-funds (bank -> wallet) and cash-out (wallet -> bank) via ACH/wire. ACH transfers are asynchronous (2-3 business days). During this window, the wallet shows "pending" funds. Uses webhooks from the bank partner to confirm settlement. Failed ACH transfers trigger a clawback from the wallet balance.
- Fraud Detection Engine -- Real-time scoring on every transaction: velocity checks (>5 transactions in 1 minute), unusual amount (10x typical), new device/location, recipient is a flagged account. High-risk transactions are held for step-up verification (PIN, biometric). Uses an ML model trained on historical fraud patterns, updated weekly.
Database Choice
PostgreSQL for the ledger and balance tables -- ACID transactions essential for financial integrity. The ledger table is append-only (immutable audit trail). Balance updates use UPDATE wallets SET balance = balance - amount WHERE user_id = ? AND balance >= amount within the same transaction as ledger writes. Redis for cached balances (read-heavy: checking balance before every purchase) and rate limiting. Kafka for transaction events consumed by fraud detection, notifications, and analytics.
Key API Endpoints
POST /api/v1/transfers
-> Body: \{ sender_id: "U1", recipient: "user@email.com", amount: 50.00, idempotency_key: "uuid-abc" \}
-> Returns: \{ transfer_id: "TXN-789", status: "COMPLETED", sender_balance: 150.00 \}
POST /api/v1/wallet/add-funds
-> Body: \{ user_id: "U1", amount: 200.00, bank_account_id: "BA-3" \}
-> Returns: \{ transfer_id: "TXN-790", status: "PENDING", estimated_completion: "2024-01-18" \}
GET /api/v1/wallet/\{user_id\}/transactions?from=2024-01-01&to=2024-01-31&type=p2p
-> Returns: \{ transactions: [\{ id, type, amount, counterparty, timestamp, status \}], balance: 350.00 \}
Scaling Insight
Double-entry bookkeeping with immutable ledger entries is both the correctness mechanism and the scaling enabler. Because ledger entries are append-only (never updated or deleted), the table is trivially partitioned by time range and the write pattern is sequential. The balance is just a cached materialized view that can be recomputed from the ledger at any time. This means: no UPDATE contention on a "balance" row (only INSERT to ledger + single atomic balance UPDATE), full audit trail for reconciliation, and the ability to shard the ledger by user_id across PostgreSQL partitions.
Key Tradeoffs
| Decision | Option A | Option B | Chosen |
|---|---|---|---|
| Balance tracking | Compute from ledger on every read | Cached balance + ledger audit | Cached balance -- O(1) reads; ledger used for nightly reconciliation |
| Transfer model | Synchronous (block until complete) | Async with eventual consistency | Synchronous for wallet-to-wallet -- users expect instant confirmation |
| Fraud detection | Post-transaction (less latency) | Pre-transaction (blocks fraud) | Pre-transaction -- adds 50ms latency but prevents fraudulent transfers from completing |
Original DosiBridge notes for Design a Digital Wallet
This section is written specifically for this page, not copied from a general system-design checklist. The useful way to study Design a Digital Wallet 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 a Digital Wallet, decide the core entity before choosing tools; otherwise the design looks clean but fails when digital changes.
- Read/Write Path: For Design a Digital Wallet, decide the read/write path before choosing tools; otherwise the design looks clean but fails when wallet changes.
- Contention Point: For Design a Digital Wallet, decide the contention point before choosing tools; otherwise the design looks clean but fails when digital changes.
- Abuse Path: For Design a Digital Wallet, decide the abuse path before choosing tools; otherwise the design looks clean but fails when wallet changes.
- Recovery Workflow: For Design a Digital Wallet, decide the recovery workflow before choosing tools; otherwise the design looks clean but fails when digital changes.
Distinct angle: wallet balance is a ledger projection
A digital wallet should treat displayed balance as a projection of immutable ledger entries, not as a mutable number that services update directly. Top-ups, holds, captures, refunds, cashback, and reversals need separate event types. That makes wallet design different from generic payments: the hardest part is preserving an auditable money trail while still showing users a fast balance update.
Design a Digital Wallet 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 a Digital Wallet 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 a Digital Wallet 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 digital-wallet health as a named dashboard or review item: combine one user-facing metric, one saturation metric, and one correctness metric. For Design a Digital Wallet, 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.