Case Study: Design a Digital Wallet

“Vi dien tu giong nhu mot cuon so cai bat tu — moi dong tien di chuyen deu duoc ghi lai duoi dang su kien, khong bao gio bi xoa, khong bao gio bi sua. A mat dung X dong, B nhan dung X dong, du he thong co crash giua chung. Do la suc manh cua event sourcing.”

Tags: system-design digital-wallet event-sourcing cqrs saga exactly-once fintech alex-xu-vol2 case-study Student: Hieu Prerequisite: Tuan-02-Back-of-the-envelope · Tuan-08-Message-Queue · Tuan-11-Microservices-Pattern Lien quan: Case-Design-Payment-System · Tuan-15-Data-Security-Encryption · Tuan-14-AuthN-AuthZ-Security · Tuan-07-Database-Sharding-Replication Reference: Alex Xu, System Design Interview Volume 2 — Chapter 12: Digital Wallet


1. Context & Why — Tai sao Digital Wallet quan trong?

1.1 Analogy: Vi dien tu MoMo / ZaloPay

Hieu, em hay tuong tuong minh dang xay he thong cho MoMo hoac ZaloPay. Moi ngay co hang trieu nguoi dung chuyen tien cho nhau — tu viec chia tien an trua 50,000 VND den chuyen tien thue nha 5,000,000 VND. Khi nguoi A chuyen 100,000 VND cho nguoi B, he thong phai dam bao mot cach tuyet doi:

  • A mat dung 100,000 VND — khong mat nhieu hon, khong mat it hon
  • B nhan dung 100,000 VND — khong nhan nhieu hon, khong nhan it hon
  • Tong so tien trong he thong khong thay doi — khong bao gio “tao ra” hoac “mat di” tien
  • Khong bao gio xay ra tinh trang A mat tien ma B khong nhan — du server crash giua chung
  • Khong bao gio xay ra tinh trang B nhan tien ma A khong mat — du network timeout
  • Giao dich chi duoc xu ly dung mot lan — du client gui lai request 5 lan

Day la bai toan kho nhat trong fintech. No khong chi la “tru va cong so du”. No la bai toan ve distributed consistency, fault tolerance, va exactly-once semantics trong he thong phan tan.

1.2 Tai sao Digital Wallet khac voi Payment System?

Khia canhPayment System (Chapter 7)Digital Wallet (Chapter 12)
FocusXu ly thanh toan qua PSP (Stripe, PayPal)Quan ly so du va chuyen tien giua cac vi noi bo
External dependencyPhu thuoc card network, bankChu yeu noi bo — kiem soat toan bo
Tinh chat tienTien “chay qua” he thongTien “nam trong” he thong
ConsistencyPSP dam bao phan lonTa phai tu dam bao — day la thach thuc lon nhat
Core patternIdempotency + webhook + reconciliationEvent sourcing + CQRS + Saga
AuditLog-basedEvent log la source of truth
Vi duShopee xu ly thanh toan qua VNPayMoMo chuyen tien tu vi A sang vi B

Key Insight: Trong payment system, em “nho” PSP (Stripe) xu ly phan kho nhat (charge card, deu phoi voi bank). Trong digital wallet, em phai tu xu ly phan kho nhat — dam bao so du chinh xac khi chuyen tien giua cac vi. Day la ly do chapter nay tap trung vao event sourcing va distributed transaction.

1.3 Tai sao Backend Dev can hieu Digital Wallet?

Ly doGiai thich
Moi super app deu co walletGrab, Gojek, MoMo, ZaloPay, WeChat Pay — wallet la core feature
Event sourcing la pattern pho bienKhong chi fintech — banking, gaming, e-commerce deu dung
CQRS la kien truc quan trongTach read va write — pattern can thiet cho he thong lon
Saga pattern cho distributed transactionKhong chi wallet — bat ky he thong microservice nao cung can
Interview favoriteDigital wallet kiem tra kha nang thiet ke he thong co consistency cao

1.4 Quy mo thuc te

Cac he thong digital wallet lon tren the gioi:

He thongQuy moDac diem
Alipay1.3 ty nguoi dung, 100,000+ TPS peak (Singles’ Day)Lon nhat the gioi
WeChat Pay900 trieu nguoi dungTich hop sieu app
MoMo35+ trieu nguoi dung tai Viet NamVi dien tu so 1 VN
GrabPay180+ trieu nguoi dung Dong Nam ASuper app wallet
PayPal430+ trieu tai khoanWallet + payment gateway

Aha Moment: MoMo xu ly hang trieu giao dich moi ngay. Moi giao dich la mot cap debit/credit. Neu chi 0.001% giao dich bi sai lech (tien mat ma khong den), voi 5 trieu giao dich/ngay = 50 giao dich bi loi. 50 khach hang goi hotline moi ngay = tham hoa dich vu. Day la ly do tai sao consistency phai la tuyet doi, khong phai “gan dung”.


2. Deep Dive — Alex Xu 4-Step Framework

Step 1: Requirements — Hieu va gioi han bai toan

2.1.1 Clarifying Questions

Cau hoiTra loiGhi chu
Chuyen tien giua ai va ai?User-to-user (P2P)Vi A chuyen sang vi B
Co ho tro nap tien / rut tien khong?Co, nhung focus chuyen tien noi boNap/rut la integration voi bank
Quy mo?1 trieu transactions/day~12 TPS trung binh, peak 50+ TPS
Exactly-once bat buoc?CoKhong duoc mat hoac tao ra tien
Multi-currency?Khong trong scope nayDon gian hoa
So du co the am?KhongBalance >= 0 luon luon
Transaction history?CoUser xem lich su giao dich
Real-time balance?CoUser thay so du ngay sau giao dich

2.1.2 Functional Requirements

IDChuc nangMo ta chi tiet
FR1Transfer moneyChuyen tien tu wallet A sang wallet B, dam bao A giam dung X va B tang dung X
FR2Balance inquiryUser xem so du hien tai cua vi — phai chinh xac va real-time
FR3Transaction historyUser xem danh sach cac giao dich da thuc hien (gui, nhan, that bai)
FR4Idempotent transferCung mot request gui nhieu lan chi duoc xu ly 1 lan
FR5Balance validationKhong cho chuyen tien neu so du khong du

2.1.3 Non-Functional Requirements

Yeu cauMuc tieuLy do
CorrectnessZero money loss/creationTien mat = kien tung, tien tao ra = gian lan
Exactly-onceMoi transfer chi thuc hien 1 lanDuplicate = mat tien hoac tao tien
ConsistencyStrong consistency cho balance updateSo du phai chinh xac tai moi thoi diem
Availability99.99% uptime (~52 phut downtime/nam)Wallet khong hoat dong = user khong the chi tieu
DurabilityZero data lossMoi giao dich phai duoc luu vinh vien
AuditabilityMoi thay doi co audit trailCompliance va dispute resolution
LatencyP99 < 500ms cho transferUser experience
Throughput1M transactions/day, peak 50 TPSScale cho viec dung hang ngay

Trade-off quan trong: Day la he thong CP (Consistency > Availability theo CAP theorem). Khi phai chon giua “cho phep giao dich sai” va “tu choi giao dich”, ta luon chon tu choi. Tham chieu Tuan-07-Database-Sharding-Replication de hieu CP vs AP.


Step 2: High-Level Design — Kien truc tong quan

2.2.1 System Components

ComponentVai troAnalogy
Wallet ServiceQuan ly vi, kiem tra so du, thuc hien chuyen tienThu ngan ngan hang
Transaction ServiceDieu phoi toan bo flow chuyen tien, dam bao atomicityGiam doc chi nhanh
Ledger ServiceGhi nhan moi giao dich theo chuan double-entrySo cai ke toan
Audit ServiceKiem tra tinh nhat quan, doi soat, phat hien bat thuongKiem toan vien
Event StoreLuu tru moi su kien (source of truth)Cuon nhat ky bat tu
Balance CacheCache so du de doc nhanhBang tin o cua ngan hang

2.2.2 High-Level Architecture

flowchart TB
    subgraph "Client Layer"
        USER_A["User A<br/>Mobile App"]
        USER_B["User B<br/>Mobile App"]
    end

    subgraph "API Gateway"
        GW["API Gateway<br/>Auth, Rate Limit,<br/>Idempotency Check"]
    end

    subgraph "Core Services"
        TXN["Transaction Service<br/>Transfer Orchestrator"]
        WALLET["Wallet Service<br/>Balance Management"]
        LEDGER["Ledger Service<br/>Double-entry Bookkeeping"]
        AUDIT["Audit Service<br/>Reconciliation & Compliance"]
    end

    subgraph "Event Infrastructure"
        ES["Event Store<br/>Append-only Log"]
        KAFKA["Message Broker<br/>Kafka"]
    end

    subgraph "Data Stores"
        WALLETDB[("Wallet DB<br/>Balance State")]
        LEDGERDB[("Ledger DB<br/>Immutable Records")]
        CACHE[("Redis<br/>Balance Cache")]
        HISTORYDB[("History DB<br/>Read-optimized")]
    end

    USER_A --> GW
    USER_B --> GW
    GW --> TXN
    TXN --> WALLET
    TXN --> LEDGER
    TXN --> ES
    TXN --> KAFKA
    WALLET --> WALLETDB
    WALLET --> CACHE
    LEDGER --> LEDGERDB
    KAFKA --> AUDIT
    KAFKA --> HISTORYDB
    AUDIT --> LEDGERDB
    AUDIT --> WALLETDB

2.2.3 Transfer Flow Overview (Happy Path)

Khi User A chuyen 100,000 VND cho User B:

1. User A → API Gateway: "Chuyen 100,000 VND cho User B" (kem idempotency_key)
2. API Gateway: Kiem tra auth, rate limit, idempotency_key (da xu ly chua?)
3. API Gateway → Transaction Service: Tao transfer request
4. Transaction Service → Wallet Service: "Kiem tra so du A >= 100,000?"
5. Wallet Service: "Co, A co 500,000 VND"
6. Transaction Service → Event Store: Ghi event "TransferInitiated"
7. Transaction Service → Wallet Service: "Debit A 100,000 VND"
8. Wallet Service → Event Store: Ghi event "DebitCompleted"
9. Transaction Service → Wallet Service: "Credit B 100,000 VND"
10. Wallet Service → Event Store: Ghi event "CreditCompleted"
11. Transaction Service → Ledger Service: Ghi double-entry (Debit A, Credit B)
12. Transaction Service → Kafka: Publish "TransferCompleted" event
13. Kafka → Audit Service: Kiem tra tinh nhat quan
14. Kafka → History DB: Ghi lich su giao dich cho A va B
15. Transaction Service → User A: "Chuyen tien thanh cong!"

Step 3: Deep Dive — Thiet ke chi tiet

Day la phan quan trong nhat cua chapter nay. Alex Xu trinh bay mot hanh trinh tu giai phap don gian nhat den giai phap production-ready, moi buoc giai quyet mot van de cu the.

3.1 In-memory Solution — Tai sao khong hoat dong

Y tuong don gian nhat: Luu so du trong memory (HashMap), khi chuyen tien thi tru A va cong B.

Van deGiai thichVi du
Race condition2 request dong thoi doc cung so du, ca 2 deu thay “du tien”, ca 2 deu truA co 100K, 2 giao dich 80K cung luc → A bi tru 160K → so du am
Data loss on crashServer restart = mat het so duMoMo crash → 35 trieu nguoi dung mat het tien
Khong distributedMot server duy nhat = single point of failureServer do = toan bo he thong chet
Khong co audit trailChi luu state, khong luu lich su thay doiKhong the dieu tra khi co tranh chap
Khong co durabilityMemory la volatile — mat dien = mat dataKhong the chap nhan cho he thong tai chinh

Bai hoc: In-memory solution chi phu hop cho prototype hoac bai tap. He thong tai chinh bat buoc phai persist data va co audit trail.

3.2 Database-based Solution — Giai phap dau tien that su

Y tuong: Dung database (PostgreSQL) voi ACID transaction de dam bao consistency.

Cach hoat dong: Trong cung mot database transaction:

  1. BEGIN TRANSACTION
  2. Kiem tra so du A >= X
  3. UPDATE wallet SET balance = balance - X WHERE user_id = A
  4. UPDATE wallet SET balance = balance + X WHERE user_id = B
  5. INSERT INTO ledger (debit A, credit B, amount X)
  6. COMMIT

Tai sao hoat dong tot (cho single database):

Dac diem ACIDAp dung cho walletKet qua
AtomicityCa debit va credit hoac ca hai thanh cong, hoac ca hai rollbackKhong bao gio A mat tien ma B khong nhan
ConsistencyConstraint: balance >= 0Khong the tru nhieu hon so du
Isolation2 giao dich dong thoi khong xung dotKhong race condition
DurabilityData duoc luu xuong disk, co WALKhong mat data khi crash

Gioi han cua database-based solution:

Gioi hanGiai thichKhi nao gap
Single database bottleneckToan bo giao dich di qua 1 DBKhi scale qua 10K TPS
Vertical scaling limitKhong the tang mai CPU/RAM cua 1 serverKhi dat gioi han phan cung
Khong distributedA va B phai nam tren cung 1 DBKhi can shard data theo user
Lock contentionNhieu giao dich cung tac dong 1 wallet gay blocking”Hot wallet” (vi nhan nhieu tien)
Cross-region impossibleTransaction khong the span across regionsKhi can multi-region deployment

Aha Moment: Database-based solution la hoan hao cho he thong nho (< 10K TPS, single region). Nhieu startup fintech bat dau voi giai phap nay va no hoat dong rat tot. Van de chi xay ra khi scale — va do la luc can chuyen sang event sourcing.

3.3 Distributed Transaction Challenge — Bai toan that su kho

Khi he thong lon len, wallet A va wallet B co the nam tren khac shard hoac khac service. Luc nay, ACID transaction cua single database khong con hoat dong.

Vi sao phai shard?

Tuong tuong MoMo co 35 trieu nguoi dung. Mot PostgreSQL instance khong the luu 35 trieu wallet va xu ly 5 trieu giao dich/ngay. Phai shard — chia wallet theo user_id ra nhieu database server.

Van de: User A (shard 1) chuyen tien cho User B (shard 2). Lam sao dam bao atomicity khi debit va credit nam tren 2 database khac nhau?

3.3.1 Two-Phase Commit (2PC) — Va tai sao no co van de

2PC la giai phap “kinh dien” cho distributed transaction:

PhaseHanh dongGiai thich
Phase 1: PrepareCoordinator hoi tat ca participant: “San sang commit chua?”Shard 1: “San sang debit A”, Shard 2: “San sang credit B”
Phase 2: CommitNeu tat ca “san sang” → Coordinator noi: “Commit!”Ca 2 shard commit dong thoi
RollbackNeu bat ky participant nao “khong san sang” → “Rollback!”Ca 2 shard rollback

Van de cua 2PC trong thuc te:

Van deGiai thichHau qua
Coordinator failureCoordinator crash sau Phase 1, truoc Phase 2Cac participant “treo” — khong biet commit hay rollback
BlockingParticipant phai giu lock cho den khi nhan lenh tu coordinatorCac giao dich khac bi block, throughput giam manh
Latency cao2 round-trip giua coordinator va tat ca participantLatency tang gap doi so voi single DB
Khong fault-tolerantMot participant crash = toan bo transaction bi blockKhong phu hop cho he thong high-availability
Network partitionCoordinator va participant khong lien lac duocTrang thai khong xac dinh — nguy hiem nhat

Key Insight: 2PC lam viec tot trong cung datacenter voi it participant. Nhung khi cross-region hoac co nhieu service, 2PC tro thanh bottleneck va single point of failure. Day la ly do tai sao cac he thong tai chinh lon khong dung 2PC ma chuyen sang event sourcing + saga.

3.4 Event Sourcing Approach — THE Key Pattern

Day la trai tim cua chapter nay. Event sourcing la pattern thay doi cach ta suy nghi ve data storage.

3.4.1 Triết lý core: Events la source of truth

Cach truyen thong (state-based):

  • Luu trang thai hien tai cua wallet: balance = 400,000 VND
  • Khi chuyen tien: UPDATE balance

Cach event sourcing (event-based):

  • Luu moi su kien da xay ra:
    • WalletCreated: user=A, initial_balance=0
    • CreditCompleted: user=A, amount=500,000, source=bank_deposit
    • DebitCompleted: user=A, amount=100,000, target=user_B, transfer_id=T001
  • Balance = replay tat ca events: 0 + 500,000 - 100,000 = 400,000 VND
So sanhState-basedEvent Sourcing
Luu giTrang thai hien taiMoi su kien da xay ra
UpdateGhi de state cuAppend event moi
Lich suMat (chi co state moi nhat)Co toan bo — tu ngay dau tien
AuditCan them audit log riengEvent log chinh la audit trail
DebugKho — chi thay state hien taiDe — replay events de thay chinh xac chuyen gi da xay ra
RebuildKhong theCo the rebuild state bat ky luc nao
StorageIt honNhieu hon (nhung storage re)
3.4.2 Events trong Digital Wallet

Moi giao dich chuyen tien tao ra chuoi events:

EventMo taData
TransferInitiatedGiao dich duoc taotransfer_id, from_wallet, to_wallet, amount, timestamp, idempotency_key
BalanceCheckedKiem tra so du thanh congtransfer_id, wallet_id, current_balance, required_amount
DebitCompletedDa tru tien tu wallet Atransfer_id, wallet_id, amount, balance_after
CreditCompletedDa cong tien vao wallet Btransfer_id, wallet_id, amount, balance_after
TransferCompletedGiao dich hoan tattransfer_id, status=SUCCESS, timestamp
TransferFailedGiao dich that baitransfer_id, status=FAILED, reason, timestamp
DebitReversedHoan tien lai cho A (compensating)transfer_id, wallet_id, amount, reason
3.4.3 Balance = Replay events (hoac Materialized View)

Cach 1: Replay tat ca events

De tinh so du wallet A, doc tat ca events lien quan den wallet A va “replay” tu dau:

Event 1: WalletCreated(A) → balance = 0
Event 2: CreditCompleted(A, +500,000) → balance = 500,000
Event 3: DebitCompleted(A, -100,000) → balance = 400,000
Event 4: CreditCompleted(A, +200,000) → balance = 600,000
Event 5: DebitCompleted(A, -50,000) → balance = 550,000
→ Current balance of A = 550,000 VND

Van de: Neu wallet A co 10,000 events, moi lan query balance phai replay 10,000 events = cham.

Cach 2: Materialized View (balance table)

Duy tri mot bang wallet_balance duoc cap nhat moi khi co event moi. Day la “materialized view” cua event stream.

Thanh phanVai tro
Event StoreSource of truth — luu toan bo events
Materialized ViewDerived data — balance duoc tinh tu events
Event ProcessorConsumer doc events va cap nhat materialized view

Aha Moment: Materialized view co the sai (bug, crash giua chung). Nhung vi ta co toan bo events, ta co the xoa materialized view va rebuild lai tu dau. Day la suc manh cua event sourcing — source of truth khong bao gio mat.

3.4.4 Idempotency via event_id

Moi event co mot event_id unique (UUID hoac hash cua content). Moi transfer co mot idempotency_key do client tao.

Flow dam bao idempotency:

1. Client gui: POST /transfer {idempotency_key: "abc-123", from: A, to: B, amount: 100K}
2. Server check: "abc-123" da ton tai trong event store chua?
   - Neu co → Tra ve ket qua cu (khong xu ly lai)
   - Neu chua → Xu ly binh thuong, luu event voi idempotency_key
Tinh huongKhong co idempotencyCo idempotency
Client gui 1 lanOKOK
Client gui 2 lan (retry do timeout)A bi tru 2 lan!Lan 2 duoc skip, tra ve ket qua lan 1
Client gui 5 lan (retry loop)A bi tru 5 lan!Chi xu ly 1 lan
3.4.5 Event Store — Append-only Log

Event store la noi luu tru tat ca events. No co nhung dac diem dac biet:

Dac diemGiai thichTai sao quan trong
Append-onlyChi them event moi, khong bao gio update hay deleteDam bao immutability — audit trail khong the bi sua
OrderedEvents duoc sap xep theo thoi gian (hoac sequence number)Replay phai theo dung thu tu
PersistentLuu tren disk voi replicationKhong mat data
QueryableCo the query events theo wallet_id, transfer_id, time rangeHo tro transaction history va audit

Lua chon cong nghe cho Event Store:

Cong ngheUu diemNhuoc diemKhi nao dung
KafkaThroughput cao, distributed, matureKho query theo criteria phuc tap, retention co limitEvent streaming giua services
EventStoreDBThiet ke danh rieng cho event sourcing, projections, subscriptionsIt mature hon, community nho honEvent sourcing la core cua he thong
PostgreSQL (append-only table)Quen thuoc, SQL query, ACIDThroughput thap hon Kafka, phai tu implement event sourcing logicHe thong nho-vua, team quen PostgreSQL
DynamoDB (append-only)Serverless, auto-scaling, high throughputVendor lock-in, query han cheAWS ecosystem

Thuc te: Nhieu he thong dung ket hop: PostgreSQL lam event store chinh (ACID, queryable) + Kafka lam event bus (distribute events den cac consumer). Day la pattern pho bien nhat.

3.4.6 CQRS — Command Query Responsibility Segregation

CQRS la pattern tach write (command) va read (query) thanh hai he thong rieng biet.

Tai sao can CQRS cho digital wallet?

Van deGiai thich
Write va read co yeu cau khac nhauWrite can consistency cao (ACID). Read can throughput cao (1000x nhieu hon write)
Event store khong toi uu cho readReplay 10,000 events de lay balance = cham. Can materialized view
Scale doc lapWrite it nhung quan trong. Read nhieu nhung co the chap nhan eventually consistent
Model khac nhauWrite model: events. Read model: bang so du, lich su giao dich — cau truc khac hoan toan
flowchart LR
    subgraph "Command Side (Write)"
        CMD["Transfer Command"]
        VALIDATE["Validate<br/>Balance Check"]
        EVTSTORE["Event Store<br/>(Source of Truth)"]
    end

    subgraph "Event Bus"
        KAFKA["Kafka<br/>Event Distribution"]
    end

    subgraph "Query Side (Read)"
        BALVIEW["Balance View<br/>(Materialized)"]
        HISTVIEW["History View<br/>(Transaction List)"]
        CACHE["Redis Cache<br/>(Hot Balance)"]
    end

    subgraph "Consumers"
        PROJ_BAL["Balance<br/>Projector"]
        PROJ_HIST["History<br/>Projector"]
    end

    CMD --> VALIDATE
    VALIDATE --> EVTSTORE
    EVTSTORE --> KAFKA
    KAFKA --> PROJ_BAL
    KAFKA --> PROJ_HIST
    PROJ_BAL --> BALVIEW
    PROJ_BAL --> CACHE
    PROJ_HIST --> HISTVIEW

    USER_WRITE["User: Transfer"] --> CMD
    USER_READ["User: Check Balance"] --> CACHE
    USER_HIST["User: View History"] --> HISTVIEW

Command side (Write path):

  1. Nhan transfer command
  2. Validate (balance check, fraud check)
  3. Ghi events vao Event Store (source of truth)
  4. Publish events len Kafka

Query side (Read path):

  1. Kafka consumer (projector) doc events
  2. Cap nhat materialized views (balance table, history table)
  3. Cap nhat Redis cache
  4. User query doc tu materialized view hoac cache
Dac diemCommand SideQuery Side
Data modelEvents (append-only)Materialized views (tables, cache)
ConsistencyStrong (ACID)Eventually consistent
ThroughputThap hon (can lock, validate)Cao hon (read-only, co cache)
ScaleKho scale (consistency requirement)De scale (them read replica, cache)
LatencyCao hon (write to disk)Thap hon (read from cache)

Aha Moment: CQRS cho phep em scale read va write doc lap. Balance inquiry (read) co the nhieu gap 100 lan so voi transfer (write). Voi CQRS, em them Redis replica va read DB replica de scale read ma khong anh huong write path.

3.4.7 Rebuilding State tu Events va Snapshots

Rebuilding state: Vi moi event duoc luu, em co the xoa toan bo materialized view va rebuild lai tu dau bang cach replay events.

Khi nao can rebuild?

  • Bug trong projector logic → sua bug → rebuild
  • Them materialized view moi (vi du: them bao cao thang)
  • Data corruption trong read model
  • Migrate sang schema moi

Van de voi replay: Wallet co 10 trieu events → replay mat hang gio.

Giai phap: Snapshots

Khia canhGiai thich
Snapshot la gi”Anh chup” cua state tai mot thoi diem cu the
Vi duSnapshot tai event #9,000,000: {wallet_A: {balance: 550,000, event_seq: 9000000}}
Khi rebuildLoad snapshot #9,000,000 → replay 1,000,000 events con lai (thay vi 10,000,000)
Tao khi naoDinh ky (moi 10,000 events, hoac moi 1 gio)
Luu o dauCung event store hoac object storage (S3)

Snapshot strategy:

StrategyTan suatUu diemNhuoc diem
Every N eventsMoi 10,000 eventsDu doan duoc rebuild timeHot wallet co snapshot nhieu, cold wallet it
Time-basedMoi 1 gioDon gianKhong toi uu cho wallet co nhieu events
On-demandKhi rebuild canIt ton storagePhai doi lau khi rebuild
HybridMoi 10,000 events HOAC moi 6 gio (cai nao den truoc)Can bangPhuc tap hon de implement

3.5 Saga Pattern cho Distributed Wallet

Khi wallet A va wallet B nam tren khac shard hoac khac service, ta khong the dung single database transaction. Saga pattern la giai phap.

3.5.1 Saga la gi?

Saga la chuoi cac local transaction, moi transaction cap nhat mot service/database. Neu mot step that bai, thuc hien compensating actions de undo cac step truoc do.

3.5.2 Transfer Saga Flow
flowchart TD
    START["Transfer Request<br/>A → B, 100,000 VND"] --> STEP1

    subgraph "Step 1: Debit"
        STEP1["Debit Wallet A<br/>-100,000 VND"]
        STEP1 -->|Success| STEP1_OK["Event: DebitCompleted"]
        STEP1 -->|Fail: Insufficient balance| STEP1_FAIL["Event: TransferFailed<br/>Reason: Insufficient funds"]
    end

    STEP1_OK --> STEP2

    subgraph "Step 2: Credit"
        STEP2["Credit Wallet B<br/>+100,000 VND"]
        STEP2 -->|Success| STEP2_OK["Event: CreditCompleted"]
        STEP2 -->|Fail: Wallet B frozen| STEP2_FAIL["Event: CreditFailed"]
    end

    STEP2_OK --> COMPLETE["Event: TransferCompleted<br/>Status: SUCCESS"]

    STEP2_FAIL --> COMPENSATE

    subgraph "Compensating Action"
        COMPENSATE["Reverse Debit A<br/>+100,000 VND"]
        COMPENSATE --> COMPENSATE_OK["Event: DebitReversed"]
        COMPENSATE_OK --> FAILED["Event: TransferFailed<br/>Reason: Credit failed, debit reversed"]
    end

    STEP1_FAIL --> ABORT["Transfer Aborted<br/>No money moved"]
3.5.3 Saga Orchestration vs Choreography
Dac diemOrchestrationChoreography
Cach hoat dongMot “orchestrator” dieu phoi tung stepMoi service tu quyet dinh hanh dong tiep theo dua tren event
Control flowTap trung tai orchestratorPhan tan giua cac service
De hieuCo — doc orchestrator la hieu toan bo flowKho — phai xem nhieu service de hieu flow
De debugCo — log tap trungKho — log phan tan
CouplingOrchestrator biet tat ca servicesServices chi biet events, khong biet nhau
Single point of failureOrchestrator la SPOFKhong co SPOF
Dung cho walletNen dung — flow phai chinh xac, de auditPhu hop hon cho flow don gian

Khuyen nghi cua Alex Xu: Voi digital wallet, dung orchestration-based saga vi:

  1. Transfer flow co thu tu nghiem ngat (debit truoc, credit sau)
  2. Can biet chinh xac trang thai cua moi step
  3. Compensating action phai duoc dieu phoi chinh xac
  4. Audit requirement cao — can log tap trung
3.5.4 Saga State Machine

Moi transfer duoc mo hinh hoa nhu state machine:

StateMo taChuyen trang thai
INITIATEDTransfer vua duoc tao→ DEBITING
DEBITINGDang tru tien tu wallet A→ DEBITED (thanh cong) hoac → FAILED (that bai)
DEBITEDDa tru tien, dang credit→ CREDITING
CREDITINGDang cong tien vao wallet B→ COMPLETED (thanh cong) hoac → COMPENSATING (that bai)
COMPLETEDGiao dich hoan tat thanh cong(terminal state)
COMPENSATINGDang hoan tien lai cho A→ COMPENSATED
COMPENSATEDDa hoan tien, giao dich that bai(terminal state)
FAILEDThat bai tu dau (balance khong du)(terminal state)

Aha Moment: State machine dam bao moi transfer chi co the o mot trang thai tai mot thoi diem, va cac chuyen trang thai la deterministic. Dieu nay cuc ky quan trong cho audit va debug.

3.6 Exactly-once Guarantee — Lam sao dam bao?

“Exactly-once” la yeu cau kho nhat trong distributed system. Thuc te, khong co exactly-once delivery trong mang. Nhung ta co the dat duoc effectively exactly-once bang cach ket hop:

Cong thuc: Idempotency + Event Dedup + At-least-once Delivery = Effectively Exactly-once

Thanh phanCach hoat dongGiai quyet van de gi
Idempotency keyClient gui kem UUID unique cho moi transfer. Server check truoc khi xu lyClient retry khong gay duplicate
Event deduplicationMoi event co unique event_id. Consumer check truoc khi processEvent duoc deliver nhieu lan nhung chi process 1 lan
At-least-once deliveryKafka dam bao moi message duoc deliver it nhat 1 lan (ack + retry)Khong mat event

Vi du cu the:

Tinh huong: User A gui "Chuyen 100K cho B". Network timeout. Client retry.

Lan 1: POST /transfer {idempotency_key: "txn-abc-123", from: A, to: B, amount: 100K}
→ Server xu ly thanh cong, luu event voi idempotency_key "txn-abc-123"
→ Response bi mat tren duong ve (network issue)

Lan 2: POST /transfer {idempotency_key: "txn-abc-123", from: A, to: B, amount: 100K}
→ Server check: "txn-abc-123" da ton tai!
→ Tra ve ket qua cu: "Transfer thanh cong" (khong xu ly lai)

Ket qua: A chi bi tru 100K mot lan. B chi nhan 100K mot lan. Chinh xac!
Neu khong co idempotencyNeu co idempotency
Lan 1: Tru A 100K, Cong B 100KLan 1: Tru A 100K, Cong B 100K
Lan 2: Tru A 100K nua, Cong B 100K nuaLan 2: Skip, tra ve ket qua cu
Tong: A mat 200K, B nhan 200K — SAITong: A mat 100K, B nhan 100K — DUNG

3.7 Handling Failures — Xu ly loi

Trong he thong phan tan, loi la chuyen binh thuong, khong phai ngoai le. Ta phai thiet ke he thong de song chung voi loi.

3.7.1 Failure Scenarios va xu ly
ScenarioGiai thichXu ly
Debit thanh cong, credit timeoutA da bi tru, nhung khong biet B da nhan chuaCheck trang thai credit → neu that bai → compensate (hoan tien A)
Debit thanh cong, credit service downA da bi tru, credit service khong phan hoiRetry voi exponential backoff → neu qua max retry → compensate
Orchestrator crash giua chungDang xu ly thi orchestrator dieOrchestrator moi khoi dong → doc saga state → tiep tuc tu step cuoi
Database crashDatabase khong ghi duoc eventRetry → neu van fail → reject transfer
Kafka consumer lagConsumer xu ly cham, balance view bi staleAlert → scale consumer → user thay balance cu nhung van dung
Network partition2 shard khong lien lac duocSaga bi “treo” → timeout → compensate → retry sau
3.7.2 Retry Strategy
AspectChi tiet
Retry policyExponential backoff: 1s → 2s → 4s → 8s → 16s
Max retries5 lan (tung ~31 giay)
JitterThem random delay de tranh “thundering herd”
IdempotentMoi retry gui cung idempotency_key → khong gay duplicate
Timeout per step5 giay cho moi saga step
3.7.3 Dead Letter Queue (DLQ)

Khi mot giao dich that bai sau tat ca retry:

BuocHanh dong
1Transfer bi day vao Dead Letter Queue
2Alert team (PagerDuty, Slack)
3Engineer dieu tra nguyen nhan
4Fix loi
5Replay tu DLQ (xu ly lai giao dich)

Key Insight: DLQ la “bang cap cuu” cho giao dich bi loi. Khong bao gio de giao dich “im lang that bai”. Moi giao dich phai co trang thai cuoi cung: SUCCESS hoac FAILED voi ly do ro rang.

3.7.4 Failure Handling Flow
flowchart TD
    REQ["Transfer Request"] --> PROCESS["Process Transfer"]
    PROCESS -->|Success| DONE["TransferCompleted"]
    PROCESS -->|Timeout / Error| RETRY{"Retry?<br/>count < max_retry?"}
    RETRY -->|Yes| WAIT["Wait<br/>(Exponential Backoff)"]
    WAIT --> PROCESS
    RETRY -->|No: max retry reached| CHECK{"Check partial state"}
    CHECK -->|Debit done, credit not| COMPENSATE["Compensate:<br/>Reverse Debit"]
    CHECK -->|Nothing done| REJECT["Reject Transfer"]
    COMPENSATE --> DLQ["Dead Letter Queue<br/>+ Alert Team"]
    REJECT --> DLQ
    DLQ --> MANUAL["Manual Review<br/>by Engineer"]
    MANUAL --> REPLAY["Replay from DLQ"]
    REPLAY --> PROCESS

3.8 Audit Trail — Moi su kien la bang chung

Mot trong nhung uu diem lon nhat cua event sourcing la audit trail mien phi.

3.8.1 Tai sao audit trail quan trong?
Ly doVi du
Dispute resolutionUser A noi “Toi khong chuyen tien nay!” → Kiem tra event log
Regulatory complianceNgan hang Nha nuoc yeu cau kiem tra giao dich → Co san
Fraud detectionPhat hien pattern bat thuong tu event log
Bug investigationTim chinh xac luc nao, event nao gay loi
Financial reconciliationDoi soat so du voi double-entry ledger
3.8.2 Event log vs Double-entry Ledger

Event sourcing tao ra event log (danh sach events). Nhung he thong tai chinh con can double-entry ledger — moi giao dich phai co debit entry va credit entry voi tong bang 0.

Giao dichDebit EntryCredit EntryTong
A → B, 100KWallet A: -100,000Wallet B: +100,0000
C → D, 50KWallet C: -50,000Wallet D: +50,0000

Reconciliation: Dinh ky (moi gio, moi ngay), Audit Service so sanh:

  • Event log: Tong so events, tong so tien di chuyen
  • Double-entry ledger: Tong debit = Tong credit? Moi giao dich co ca 2 entry?
  • Materialized balance: Tong tat ca balance = Tong tien trong he thong?

Neu bat ky phep kiem tra nao khong khop → Alert ngay lap tuc.

3.8.3 Reconciliation Pipeline
flowchart LR
    subgraph "Data Sources"
        EVT["Event Store"]
        LEDGER["Double-entry<br/>Ledger"]
        BAL["Balance<br/>Materialized View"]
    end

    subgraph "Reconciliation Engine"
        RECON["Reconciliation<br/>Service"]
        RULE["Rule Engine<br/>Comparison Rules"]
    end

    subgraph "Output"
        OK["Match ✓<br/>All consistent"]
        MISMATCH["Mismatch ✗<br/>Discrepancy Found"]
    end

    subgraph "Action"
        ALERT["PagerDuty Alert"]
        REPORT["Discrepancy Report"]
        AUTO_FIX["Auto-fix<br/>(if safe)"]
    end

    EVT --> RECON
    LEDGER --> RECON
    BAL --> RECON
    RECON --> RULE
    RULE --> OK
    RULE --> MISMATCH
    MISMATCH --> ALERT
    MISMATCH --> REPORT
    MISMATCH --> AUTO_FIX

3.9 Balance Cache — Redis cho Real-time Query

3.9.1 Tai sao can cache?
MetricKhong co cacheCo Redis cache
Balance query latency10-50ms (database read)1-2ms (Redis read)
Database loadCao (moi balance check = 1 DB query)Thap (chi khi cache miss)
Scale readKho (database bottleneck)De (them Redis replica)
3.9.2 Cache Invalidation Strategy
StrategyMo taDung khi
Write-throughCap nhat cache ngay khi ghi eventBalance phai chinh xac ngay sau transfer
Event-drivenKafka consumer cap nhat cache khi nhan eventChap nhan delay vai ms
TTL-basedCache het han sau N giay, doc lai tu DBBalance hien thi (khong can 100% real-time)

Chien luoc khuyen nghi: Write-through + TTL backup

  1. Khi DebitCompleted/CreditCompleted → cap nhat Redis ngay lap tuc
  2. Dat TTL 60 giay cho moi cache entry → neu write-through fail, cache se expire va doc lai tu DB
  3. Balance check truoc khi debit → doc tu database (khong phai cache) de dam bao strong consistency

Aha Moment: Balance hien thi cho user co the doc tu cache (eventually consistent — chap nhan sai lech vai ms). Nhung balance kiem tra truoc khi tru tien phai doc tu database (strong consistency). Day la vi du kinh dien cua viec dung consistency level khac nhau cho cac use case khac nhau.

3.10 Historical Balance — So du tai mot thoi diem trong qua khu

3.10.1 Tai sao can historical balance?
Use caseVi du
Statement generation”So du cua toi luc 23:59 ngay 31/12/2025 la bao nhieu?”
Dispute resolution”Luc 14:30 so du cua toi la 500K, tai sao giao dich 200K bi tu choi?”
Regulatory reportingBao cao so du cuoi ngay/cuoi thang cho ngan hang nha nuoc
AuditKiem tra so du tai bat ky thoi diem nao
3.10.2 Cach implement
CachMo taUu diemNhuoc diem
Event replayReplay events tu dau den thoi diem canChinh xac tuyet doiCham voi nhieu events
Snapshot + replayLoad snapshot gan nhat truoc thoi diem, replay events con laiNhanh honCan luu nhieu snapshots
Temporal tableDatabase luu moi phien ban cua row (valid_from, valid_to)Query nhanhStorage lon, schema phuc tap
Daily snapshotLuu so du cuoi moi ngayDon gian, query nhanhChi co do chinh xac theo ngay

Khuyen nghi: Daily snapshot + event replay khi can chinh xac

  • Moi ngay 00:00: Chup snapshot so du cua tat ca wallets
  • Khi user hoi “so du luc 14:30 ngay 15/3”: Load snapshot ngay 15/3 (00:00) → replay events tu 00:00 den 14:30
  • Nhanh hon replay tu dau rat nhieu

3. Estimation — Uoc luong hieu nang

3.1 Transaction QPS

3.2 Event Store Growth

Moi transfer tao ra trung binh 5 events (Initiated, BalanceChecked, Debit, Credit, Completed).

Moi event trung binh 500 bytes (JSON voi metadata):

Voi retention 7 nam (yeu cau phap ly):

Nhan xet: 7 TB la hoan toan quan ly duoc voi PostgreSQL hoac DynamoDB. Khong can giai phap luu tru dac biet.

3.3 Balance Query QPS

User check balance thuong xuyen hon chuyen tien (trung binh 10 lan check balance cho moi 1 lan transfer):

Voi Redis cache (P99 latency < 2ms), day la con so nho — mot Redis instance co the xu ly 100,000+ QPS.

3.4 Snapshot Frequency

Neu chon snapshot moi 10,000 events cho moi wallet:

Nhu vay, voi strategy “moi 10,000 events”, hau het wallet chi can 1 snapshot trong 5 nam. Nen ket hop voi daily snapshot de toi uu rebuild time.

3.5 Ledger Storage

Moi transaction tao 2 ledger entries (debit + credit), moi entry 200 bytes:

3.6 Bandwidth

Ket luan: Digital wallet la bai toan consistency-intensive, khong phai throughput-intensive hay bandwidth-intensive. Thach thuc khong nam o scale, ma nam o dam bao chinh xac tuyet doi voi moi giao dich.


4. Security — Bao mat he thong tai chinh

4.1 Encryption of Financial Data

TangBien phapGiai thich
Data at restAES-256 encryption cho database va event storeDu ai truy cap disk cung khong doc duoc data
Data in transitTLS 1.3 cho moi giao tiep giua servicesKhong the nghe len network traffic
Field-level encryptionEncrypt truong nhay cam (balance, account_id) riengDu database bi compromise, data van an toan
Key managementAWS KMS hoac HashiCorp VaultKhong luu key trong code hoac config file
Encryption key rotationThay key dinh ky (moi 90 ngay)Giam thiet hai neu key bi lo

4.2 Fraud Detection

Ky thuatMo taVi du
Velocity checkGioi han so giao dich trong khoang thoi gianToi da 10 giao dich/phut, toi da 50 trieu/ngay
Unusual pattern detectionPhat hien giao dich bat thuong so voi lich suUser thuong chuyen 50K-200K, dot nhien chuyen 50 trieu
Geo-anomalyGiao dich tu dia diem bat thuongDang o Ha Noi ma co giao dich tu Cambodia
Device fingerprintingGiao dich tu thiet bi laGiao dich tu thiet bi moi chua bao gio dung
Graph analysisPhat hien mang luoi chuyen tien dang ngo10 tai khoan moi chuyen tien vong quanh (money laundering)
ML-based scoringCham diem rui ro cho moi giao dichScore > 0.8 → block va yeu cau xac minh

4.3 AML (Anti-Money Laundering) Compliance

Yeu cauMo ta
KYC (Know Your Customer)Xac minh danh tinh truoc khi cho phep giao dich lon
Transaction monitoringTheo doi giao dich lon (tren 200 trieu VND phai bao cao NHNN)
Suspicious Activity Report (SAR)Bao cao giao dich dang ngo cho co quan chuc nang
Sanction screeningKiem tra danh sach den quoc te (OFAC, UN)
Record keepingLuu tru giao dich toi thieu 5-7 nam

4.4 Authentication cho Transfers

BuocMo taTai sao
Session authJWT token cho moi requestXac nhan danh tinh user
2FA cho transfer lonOTP qua SMS/app cho giao dich tren nguong (5 trieu VND)Ngan chan unauthorized transfer
PIN/BiometricYeu cau PIN hoac van tay truoc moi transferBao ve ngay ca khi dien thoai bi mat
Device bindingRang buoc vi voi thiet bi cu theKhong the truy cap vi tu thiet bi la

4.5 PCI-DSS (neu lien ket the)

Neu digital wallet cho phep lien ket the ngan hang (nhu MoMo lien ket Visa/Mastercard):

Yeu cau PCI-DSSMo ta
Khong luu card number tren serverDung tokenization (thay card number bang token)
Network segmentationTach mang xu ly the rieng
Penetration testingTest bao mat dinh ky (hang quy)
Access controlChi nguoi duoc uy quyen moi truy cap cardholder data
Logging & monitoringGhi log moi truy cap vao cardholder data

Key Insight: Security trong fintech khong chi la ky thuat. No bao gom process (KYC, SAR), compliance (PCI-DSS, AML), va monitoring (fraud detection). Tham chieu Tuan-15-Data-Security-Encryption va Tuan-14-AuthN-AuthZ-Security de hieu sau hon.


5. DevOps — Giam sat va van hanh

5.1 Key Metrics can giam sat

MetricMo taThreshold canh bao
Transaction success rateTy le giao dich thanh cong< 99.9% → P1 alert
Transaction latency (P50, P99)Thoi gian xu ly giao dichP99 > 500ms → investigate
Event processing lagDo tre giua ghi event va cap nhat materialized view> 5 giay → scale consumer
Balance consistency checkKet qua reconciliation dinh kyAny mismatch → P0 alert (critical)
Dead letter queue depthSo giao dich bi stuck> 0 trong 5 phut → investigate
Kafka consumer lagSo message chua duoc xu ly> 10,000 → scale consumer
Snapshot freshnessThoi gian tu snapshot gan nhat> 24h → tao snapshot moi
Cache hit rateTy le balance query hit cache< 90% → kiem tra cache strategy
Error rate by typePhan loai loi: timeout, insufficient balance, system errorSystem error > 0.1% → investigate

5.2 Reconciliation Schedule

LoaiTan suatMo ta
Real-timeMoi giao dichKiem tra debit + credit = 0 cho moi transfer
Micro-batchMoi 5 phutSo sanh event count voi ledger entry count
HourlyMoi gioTong balance tat ca wallets = tong tien trong he thong
DailyMoi ngay 01:00Full reconciliation: event store vs ledger vs balance view
MonthlyCuoi thangBao cao cho compliance va ke toan

5.3 Alerting Hierarchy

LevelTinh huongHanh dong
P0 (Critical)Balance mismatch phat hien boi reconciliationTat ca engineer on-call, dung giao dich moi neu can, fix ngay
P1 (High)Transaction success rate < 99.9%On-call engineer dieu tra trong 15 phut
P2 (Medium)Event processing lag > 10 giayEngineer dieu tra trong 1 gio
P3 (Low)Cache hit rate giamXem xet trong sprint tiep theo

5.4 Disaster Recovery

ScenarioRTORPOStrategy
Single server failure< 1 phut0 (no data loss)Auto-failover (database replica, service restart)
Database failure< 5 phut0Synchronous replication + auto-failover
Datacenter failure< 30 phut< 1 giayCross-region replication, DNS failover
Event store corruption< 2 gio0Backup + replay tu backup

5.5 Deployment Strategy

StrategyMo taAp dung cho wallet
Blue-green deployment2 moi truong giong het, chuyen traffic khi san sangCho stateless services (API gateway, fraud detection)
Canary releaseDeploy cho 1-5% traffic truoc, roi mo rongCho wallet service (can kiem tra consistency truoc khi rollout)
Feature flagBat/tat feature khong can deploy laiCho tinh nang moi (new transfer type, new validation rule)

Tham chieu: Tuan-13-Monitoring-Observability de hieu sau ve monitoring va alerting strategy.


6. Architecture Diagrams (Mermaid)

6.1 Event Sourcing Flow chi tiet

sequenceDiagram
    participant Client
    participant API as API Gateway
    participant TXN as Transaction Service
    participant ES as Event Store
    participant WS as Wallet Service
    participant KAFKA as Kafka
    participant PROJ as Balance Projector
    participant CACHE as Redis Cache
    participant LEDGER as Ledger Service

    Client->>API: POST /transfer<br/>{idempotency_key, from, to, amount}
    API->>API: Check idempotency_key
    API->>TXN: Forward request

    TXN->>ES: Write: TransferInitiated
    TXN->>WS: Check balance(from_wallet)
    WS-->>TXN: balance >= amount ✓

    TXN->>ES: Write: DebitCompleted
    TXN->>WS: Debit(from_wallet, amount)
    WS->>CACHE: Invalidate from_wallet cache

    TXN->>ES: Write: CreditCompleted
    TXN->>WS: Credit(to_wallet, amount)
    WS->>CACHE: Invalidate to_wallet cache

    TXN->>ES: Write: TransferCompleted
    TXN->>LEDGER: Record double-entry
    TXN->>KAFKA: Publish TransferCompleted

    KAFKA->>PROJ: Consume event
    PROJ->>CACHE: Update balance cache

    TXN-->>Client: Transfer successful

6.2 CQRS Read/Write Separation chi tiet

flowchart TB
    subgraph "Write Path (Command)"
        W_CLIENT["Client:<br/>Transfer Request"]
        W_VALIDATE["Validation<br/>• Balance check (from DB)<br/>• Fraud check<br/>• Idempotency check"]
        W_EVENT["Event Store<br/>(Append-only, Immutable)<br/>Source of Truth"]
        W_DB["Wallet DB<br/>(State Update)"]
    end

    subgraph "Event Distribution"
        KAFKA["Kafka<br/>Event Topics:<br/>• wallet.events<br/>• transfer.events"]
    end

    subgraph "Read Path (Query)"
        R_BAL_PROJ["Balance Projector<br/>Consume events →<br/>Update balance view"]
        R_HIST_PROJ["History Projector<br/>Consume events →<br/>Update history view"]
        R_CACHE["Redis<br/>Balance Cache<br/>(P99 < 2ms)"]
        R_BAL_DB["Balance View DB<br/>(Read-optimized)"]
        R_HIST_DB["History View DB<br/>(Read-optimized,<br/>Paginated)"]
    end

    subgraph "Read Clients"
        R_BAL_CLIENT["Client:<br/>Check Balance"]
        R_HIST_CLIENT["Client:<br/>View History"]
    end

    W_CLIENT --> W_VALIDATE
    W_VALIDATE --> W_EVENT
    W_VALIDATE --> W_DB
    W_EVENT --> KAFKA

    KAFKA --> R_BAL_PROJ
    KAFKA --> R_HIST_PROJ

    R_BAL_PROJ --> R_CACHE
    R_BAL_PROJ --> R_BAL_DB
    R_HIST_PROJ --> R_HIST_DB

    R_BAL_CLIENT --> R_CACHE
    R_BAL_CLIENT -.->|Cache miss| R_BAL_DB
    R_HIST_CLIENT --> R_HIST_DB

6.3 Saga Pattern cho Transfer chi tiet

stateDiagram-v2
    [*] --> INITIATED: Transfer Request received

    INITIATED --> VALIDATING: Validate balance & fraud
    VALIDATING --> DEBITING: Validation passed
    VALIDATING --> REJECTED: Validation failed<br/>(insufficient balance,<br/>fraud detected)

    DEBITING --> DEBITED: Debit successful
    DEBITING --> FAILED: Debit failed<br/>(DB error, timeout)

    DEBITED --> CREDITING: Proceed to credit
    CREDITING --> COMPLETED: Credit successful
    CREDITING --> COMPENSATING: Credit failed<br/>(wallet frozen,<br/>DB error)

    COMPENSATING --> COMPENSATED: Debit reversed<br/>successfully
    COMPENSATING --> STUCK: Compensation failed<br/>→ Dead Letter Queue

    COMPLETED --> [*]
    COMPENSATED --> [*]
    REJECTED --> [*]
    FAILED --> [*]
    STUCK --> MANUAL_REVIEW: Engineer investigates
    MANUAL_REVIEW --> [*]

6.4 Reconciliation Pipeline chi tiet

flowchart TB
    subgraph "Scheduled Trigger"
        CRON["Cron Job<br/>Every 1 hour"]
    end

    subgraph "Data Collection"
        EVT_COUNT["Event Store<br/>Count events<br/>per time window"]
        LEDGER_COUNT["Ledger DB<br/>Count entries<br/>per time window"]
        BAL_SUM["Balance View<br/>Sum all balances"]
        EXPECTED["Expected Total<br/>(Initial deposits<br/>minus withdrawals)"]
    end

    subgraph "Comparison Rules"
        RULE1["Rule 1:<br/>Event count = Ledger entry count?"]
        RULE2["Rule 2:<br/>Sum(all balances) = Expected total?"]
        RULE3["Rule 3:<br/>For each transfer:<br/>debit amount = credit amount?"]
        RULE4["Rule 4:<br/>No negative balances?"]
    end

    subgraph "Results"
        MATCH["ALL MATCH<br/>System consistent"]
        DISC["DISCREPANCY<br/>Mismatch found"]
    end

    subgraph "Actions"
        LOG["Log result<br/>to audit DB"]
        ALERT["P0 Alert:<br/>PagerDuty + Slack"]
        REPORT["Generate<br/>discrepancy report"]
        FREEZE["Optional:<br/>Freeze affected wallets"]
    end

    CRON --> EVT_COUNT
    CRON --> LEDGER_COUNT
    CRON --> BAL_SUM
    CRON --> EXPECTED

    EVT_COUNT --> RULE1
    LEDGER_COUNT --> RULE1
    BAL_SUM --> RULE2
    EXPECTED --> RULE2
    EVT_COUNT --> RULE3
    LEDGER_COUNT --> RULE3
    BAL_SUM --> RULE4

    RULE1 --> MATCH
    RULE2 --> MATCH
    RULE3 --> MATCH
    RULE4 --> MATCH

    RULE1 --> DISC
    RULE2 --> DISC
    RULE3 --> DISC
    RULE4 --> DISC

    MATCH --> LOG
    DISC --> ALERT
    DISC --> REPORT
    DISC --> FREEZE

7. Aha Moments & Pitfalls

7.1 Aha Moments — Nhung khoang khac “a ha”

#InsightGiai thich
1Event sourcing lam audit tro nen trivialKhong can xay audit system rieng. Event log chinh la audit trail. Moi thay doi da duoc ghi lai tu dong, khong the bi xoa hoac sua.
2CQRS cho phep scale read va write doc lapBalance inquiry (read) nhieu gap 10-100x so voi transfer (write). CQRS cho phep them Redis replica, read DB replica ma khong anh huong write path.
3Exactly-once khong phai ve delivery, ma ve idempotencyKhong the dam bao network chi gui message 1 lan. Nhung co the dam bao server chi xu ly message 1 lan bang idempotency key. At-least-once delivery + idempotent processing = effectively exactly-once.
4Event store co the rebuild moi thuMaterialized view bi hong? Xoa va rebuild. Them bao cao moi? Replay events. Migrate schema? Replay events voi logic moi. Source of truth khong bao gio mat.
5Saga la “distributed ACID” voi trade-offsSaga khong cho atomicity nhu single DB transaction. No cho eventual consistency voi compensating actions. Nhung do la cai gia phai tra de co scalability va availability.
6Snapshot la chia khoa de event sourcing hoat dong trong thuc teEvent sourcing ly thuyet thi dep, nhung replay 10 trieu events de lay balance la khong kha thi. Snapshot + partial replay lam cho no thuc te duoc.
7Consistency level phai khac nhau cho cac use case khac nhauBalance hien thi cho user: eventually consistent (tu cache) la OK. Balance check truoc khi debit: bat buoc strong consistency (tu database). Khong phai moi thu deu can strong consistency.
8Dead Letter Queue la mang an toanTrong he thong tai chinh, khong bao gio de giao dich “bien mat”. DLQ dam bao moi giao dich that bai deu duoc ghi nhan va xu ly.

7.2 Pitfalls — Nhung cai bay thuong gap

#PitfallTai sao nguy hiemCach tranh
1Doc balance tu cache de kiem tra truoc khi debitCache co the stale. User A co 100K trong DB nhung cache hien thi 200K (chua cap nhat). Neu debit 150K dua tren cache → so du am.Luon doc tu database (strong consistency) khi kiem tra balance cho debit. Cache chi dung cho display.
2Khong co idempotency keyClient retry → duplicate transfer → user mat tien gap doiBat buoc idempotency key cho moi transfer request.
3Dung 2PC cho cross-shard transferCoordinator failure → giao dich bi block → lock contention → throughput giamDung Saga pattern thay vi 2PC.
4Khong co compensating actionCredit fail sau khi debit thanh cong → user A mat tien vinh vienMoi saga step phai co compensating action tuong ung.
5Replay events khong theo thu tuEvents bi xao tron → balance tinh saiDam bao strict ordering trong event store. Dung sequence number, khong chi dua vao timestamp.
6Khong co reconciliationBug im lang tao ra money discrepancy, chi phat hien khi qua treReconciliation dinh ky (hourly, daily). Bat ky mismatch nao deu phai la P0 alert.
7Event store khong immutableAi do UPDATE hoac DELETE event → mat audit trail, mat source of truthEvent store phai append-only. Dung database permissions de ngan UPDATE/DELETE.
8Khong co DLQGiao dich fail → mat tich → user khong biet chuyen gi da xay raMoi giao dich fail phai vao DLQ. Khong bao gio ignore failure.
9Snapshot khong consistent voi event storeSnapshot bi loi → rebuild balance saiSnapshot phai bao gom event sequence number. Khi rebuild, chi replay events sau sequence number cua snapshot.
10Eventually consistent la OK cho moi thuBalance display eventually consistent la OK. Nhung balance check cho debit phai strong consistent. Nham lan 2 cai nay → money loss.Phan biet ro: display (eventual OK) vs business logic (strong required).

7.3 Interview Tips

TipGiai thich
Bat dau tu single DB solutionCho thay em hieu van de can giai quyet truoc khi nhay vao giai phap phuc tap
Giai thich tai sao can event sourcingKhong phai vi “no cool”, ma vi no giai quyet van de cu the: audit trail, rebuild state, distributed consistency
Ve state machine cho sagaInterviewer thich thay em suy nghi co cau truc ve trang thai va chuyen trang thai
Noi ve trade-offsEvent sourcing co nhuoc diem (storage, complexity, eventual consistency). Phai biet va noi ro
Mention reconciliationRat it ung vien nghi den reconciliation. Day la diem khac biet giua “thiet ke tren giay” va “thiet ke cho production”

8. Tong ket — Mental Model

8.1 Digital Wallet = Event Sourcing + CQRS + Saga

┌─────────────────────────────────────────────────────────┐
│                   DIGITAL WALLET                        │
│                                                         │
│  ┌──────────────────┐   ┌──────────────────┐           │
│  │   Event Sourcing │   │      CQRS        │           │
│  │   • Source of     │   │   • Write: events │           │
│  │     truth = events│   │   • Read: views   │           │
│  │   • Immutable log │   │   • Scale doc lap │           │
│  │   • Rebuild state │   │                    │           │
│  └──────────────────┘   └──────────────────┘           │
│                                                         │
│  ┌──────────────────┐   ┌──────────────────┐           │
│  │   Saga Pattern   │   │  Exactly-once     │           │
│  │   • Distributed   │   │   • Idempotency   │           │
│  │     transaction   │   │     key            │           │
│  │   • Compensating  │   │   • Event dedup    │           │
│  │     actions       │   │   • At-least-once  │           │
│  └──────────────────┘   └──────────────────┘           │
│                                                         │
│  ┌──────────────────┐   ┌──────────────────┐           │
│  │   Reconciliation │   │   Audit Trail     │           │
│  │   • Hourly/daily  │   │   • Free with     │           │
│  │   • Event vs      │   │     event sourcing│           │
│  │     ledger vs     │   │   • Immutable      │           │
│  │     balance       │   │   • Complete       │           │
│  └──────────────────┘   └──────────────────┘           │
└─────────────────────────────────────────────────────────┘

8.2 Khi nao dung giai phap nao?

ScaleGiai phapKhi nao
Startup (< 1K TPS)Single PostgreSQL voi ACID transactionKhi bat dau, don gian, de hieu, de maintain
Growth (1K-10K TPS)PostgreSQL + Event sourcing + CQRSKhi can audit trail, khi read/write ratio khong can bang
Scale (10K-100K TPS)Sharded event store + Saga + CQRS + Redis cacheKhi single DB khong du, can distributed transaction
Massive (100K+ TPS)Full architecture nhu tren + multi-region + dedicated event storeAlipay, WeChat Pay level

Loi khuyen cuoi cung: Hieu, hay nho rang don gian la tot nhat. Bat dau voi single database transaction. Chi them event sourcing, CQRS, saga khi thuc su can. Premature optimization la root of all evil — dac biet trong fintech, noi ma correctness quan trong hon performance.


LinkLy do lien quan
Case-Design-Payment-SystemPayment system la “anh em” voi digital wallet — cung domain fintech, nhung focus khac (external PSP vs internal wallet)
Tuan-11-Microservices-PatternSaga pattern, event-driven architecture, service communication — tat ca la microservice patterns
Tuan-08-Message-QueueKafka la backbone cua event distribution trong CQRS. Hieu message queue de hieu event streaming
Tuan-15-Data-Security-EncryptionEncryption, key management, PCI-DSS — bao mat la bat buoc cho he thong tai chinh
Tuan-14-AuthN-AuthZ-Security2FA, session auth, device binding — authentication la tuyen phong thu dau tien
Tuan-07-Database-Sharding-ReplicationSharding wallet data, replication cho durability — hieu database scaling de hieu tai sao can distributed transaction
Tuan-02-Back-of-the-envelopeEstimation section su dung ky thuat tu tuan nay
Tuan-13-Monitoring-ObservabilityMonitoring, alerting, reconciliation — DevOps section xay dung tren kien thuc observability