Digital Wallet — Detailed#
flowchart TB
subgraph Apps
APP([Mobile wallet])
WEB([Web])
end
subgraph Edge
CDN
GW
end
subgraph Core
USERS([User / KYC])
LINK[Link bank / card]
BAL[Balance Service]
TX[Transaction Service]
CASHIN[Top-up / Cash in]
CASHOUT[Cash out / Withdraw]
P2P[Send to friend]
MERCH[Pay to merchant]
BILL[Bill pay]
RECUR[Subscriptions]
end
subgraph Ledger[Ledger - source of truth]
DBLEDGER[(Double-entry ledger)]
ACCT([(Per-user account / sub-accounts)])
LOCK[Pessimistic / OCC locking]
JRN[Journal]
end
subgraph Rails[External rails]
UPI
SWIFT
ACH
SEPA
CARD[Card network]
NEFT_IMPS
end
subgraph Risk
RISK[Fraud detection]
LIMIT[Velocity limits]
KYC[KYC / AML / sanctions]
PEP[PEP screening]
end
subgraph Compliance
AUD[Audit log immutable]
REG[Regulator reporting]
HOLD[Funds hold rules]
end
subgraph Webhooks
EVT[[Event bus]]
OUT[Outbound webhooks]
end
Apps --> CDN --> GW --> Core
Core --> Ledger
Core --> Rails
Core --> Risk
Core --> Compliance
Core --> Webhooks
classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
class APP,WEB,USERS client;
class LINK,BAL,TX,CASHIN,CASHOUT,P2P,MERCH,BILL,RECUR,LOCK,JRN,CARD,RISK,LIMIT,KYC,PEP,REG,HOLD,OUT service;
class DBLEDGER,ACCT datastore;
class EVT queue;
class AUD obs;
Ledger correctness#
- Every transfer = 2 entries (credit + debit) in atomic transaction.
- Use SERIALIZABLE or SI with retry on conflict.
- Never store balance as a single mutable row — compute or maintain via summary table with version.
Send-money flow#
- Idempotent
POST /transfer { from, to, amount, idem_key }. - Validate KYC + balance + limits.
- Lock both accounts (canonical order to avoid deadlock).
- Insert journal entries.
- Emit event.
- Notify both users.
External rails#
- Each rail has its own latency + cutoff + reconciliation file.
- Pending → settled state machine; reconcile statements daily.
Glossary & fundamentals#
Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.
| Tag | Concept | What it is | Page |
|---|---|---|---|
HLD |
CDN | edge caching for static assets | cdn |
HLD |
MVCC & isolation levels | snapshot isolation, serializability, vacuum | mvcc-isolation-levels |
HLD |
Idempotency & retries | safe re-execution, backoff + jitter | idempotency-retries |
LLD |
State machines | FSM, HSM, transitions, guards | state-machines |
LLD |
Behavioural patterns | Strategy, Observer, State, Command, Chain | behavioral-patterns |
LLD |
Concurrency primitives | mutex, semaphore, RW lock, atomic, CAS | concurrency-primitives |
LLD |
Threading & deadlocks | thread states, Coffman, lock ordering | threading-and-deadlocks |
LLD |
Immutability | immutable types, persistent collections | immutability |