System Design

Ledger Service

Design a double-entry ledger service for a fintech like Ramp or Wise.

Functional requirements

  • Internal services post transactions, each a set of entries that debit some accounts and credit others (e.g., a card swipe debits the cardholder's spend account and credits the merchant payable account); a transaction whose debits and credits do not sum to zero is rejected.
  • Any service can read an account's current balance, and a posting can be made conditional on a minimum balance (e.g., decline the swipe if the available balance is below the amount).
  • Callers can read an account's balance as of any past instant and list the entries that touched an account in a time range (e.g., a statement for last month).
  • Entries are never updated or deleted; corrections and reversals are posted as new transactions that reference the original.
  • The ledger exposes a consistency report: every account's balance equals the sum of its entries and the whole book sums to zero, with any discrepancy flagged.

Non-functional requirements

  • Posting is on the critical path of card authorizations: p99 under 50ms for a balance-checked posting and under 20ms for a plain balance read.
  • Strong consistency for postings and balances: a posting is recorded in full (all its entries) or not at all, and a balance read after a successful posting reflects it; historical and as-of queries may lag by a few seconds.
  • Durability: an acknowledged posting is never lost, entries are immutable, and the full history is retained for 10 years and must be reproducible for audit.
  • The posting path is available 99.99% of the time (about 1 hour of downtime per year); when the ledger cannot guarantee correctness (e.g., primary unreachable), it rejects postings rather than accepting them provisionally.
  • Every posting carries the calling service's identity and a caller-supplied transaction id; a transaction id already recorded is rejected, and all postings are audit-logged with their caller.

Scaling & constraints

  • 50M accounts; ~5,000 entries per second sustained across ~2,000 transactions per second, with peaks of 3x during business hours.
  • Read:write ratio of roughly 5:1 for current balance reads vs. postings; as-of and statement queries are under 1% of reads but scan far more data.
  • Hot accounts: fewer than 20 internal accounts (interchange clearing, fee revenue, a few large customers' operating accounts) absorb ~60% of all entries, and the hottest single account receives up to 2,000 entries per second at peak, while 95% of accounts see fewer than 10 entries per day.
  • Each entry is ~200 bytes and a transaction averages 2.5 entries; that is ~13B entries per month (~2.6 TB/month), retained for 10 years, with volume growing 50% per year.
  • Balance-checked postings (authorizations) are ~40% of postings and latency sensitive; the other 60% (settlement, fees, payouts) arrive in batch files of up to 1M entries and are not.
  • Downstream consumers (reporting, reconciliation, statements) need every entry delivered at least once within 30 seconds of commit.

Out of scope

  • Multi-currency accounts and foreign exchange.
  • Charge creation, idempotent retries against card networks, and processor integration (assume the payment system has already decided what to post).
  • Interest, fees, and product pricing logic.
  • External financial reporting, tax, and export to accounting software.

Sign in to save your progress

AI design evaluation

Get a score, what your board does well, what to fix first, and what an interviewer would ask next.

Sign in to evaluate

Sign in to get AI feedback on your design.