EN 中文

System Design Lab

A payment ledger is bound by correctness, not QPS: money must never be created, lost, or double-charged.

Change payment rate, idempotency-key TTL, external provider latency, total ledger entries, the reconciliation window, and regions. The design adds correctness mechanisms first — idempotency keys, a double-entry append-only ledger, ACID writes, an async PSP state machine — and only partitions by account once integrity is locked down.

Guided walkthrough

Reason about it one step at a time

Normal evolution scenarios

Click left to right for the intended demo path. Each card changes the workload inputs.

Workload

These are inputs, not preset architecture stages.

Recommended shape

Current architecture path
Payment ledger architecture diagram Whiteboard-style architecture diagram for a payment + ledger system: clients, a payment API with an idempotency layer, a double-entry ledger service, an ACID datastore with account partitions, and an async tier of PSP adapter, reconciliation, and audit log. Clients Payment API Ledger Datastore Async + audit Client submits + retries Payment API request handling Idempotency layer dedup retries Ledger service double-entry ACID store transactional Account shards partition by account PSP adapter async capture Reconciliation match records Audit log event trail
Clients
Client submits payments and retries on timeout, sometimes resending the same request
Payment API
Payment API validates payment requests and owns the payment state machine
Idempotency layer stores idempotency keys so a retried request is processed exactly once
Ledger
Ledger service records balanced debits and credits as the immutable source of truth
Datastore
ACID store commits balanced entries atomically and durably
Account shards partitions the ledger by account so writes scale without breaking balance
Async + audit
PSP adapter authorizes and captures through the slow external provider with retries and a DLQ
Reconciliation re-fetches provider records and re-balances them against the ledger
Audit log keeps an append-only event trail of every state transition for compliance

Bottlenecks

Ledger write load

Idempotency-store load

PSP-bound async backlog

Ledger storage growth

Reconciliation lag

Why this changes

    Decision tradeoffs

    Idempotency layer

    Double-entry ledger

    Transaction model

    PSP integration

    Reconciliation

    Audit / event log

    Source-backed rules

    These are the durable system-design claims behind the model. The exact slider thresholds are deliberately labeled as teaching assumptions.

    Verified rule

    Idempotency keys make a retried payment request safe to replay

    Stripe lets clients attach an idempotency key so retries from network failures return the original result instead of creating a second charge.

    Stripe Docs
    Verified rule

    Capture funds asynchronously because the provider is slow and can fail

    A PaymentIntent moves through requires_action, processing, and succeeded states; treating capture as an async state machine tolerates provider latency and failures.

    Stripe Docs
    Verified rule

    A double-entry, append-only ledger is the immutable source of truth

    Modeling money as balanced postings to accounts keeps the ledger auditable and self-checking, so balances are derived rather than mutated in place.

    martinfowler.com
    Verified rule

    Event sourcing keeps a full, replayable audit trail of state changes

    Persisting every state transition as an immutable event gives a complete audit log and lets balances be rebuilt by replaying history.

    martinfowler.com

    Teaching assumptions

    • Correctness is the binding constraint; single-node throughput and storage budgets are conservative teaching numbers, not vendor limits.
    • Each payment is modeled as one balanced double-entry write; the idempotency store sees roughly one lookup per attempt including retries.
    • PSP-bound backlog is approximated from payment rate times provider latency, i.e. the in-flight captures waiting on the external provider.