Design a ledger
Design an internal ledger system that allows merchants to record transactions and query account balances for companies.
Asked at:
Stripe
An internal ledger is a double-entry accounting system that records every money movement as balanced debits and credits between accounts, and answers balance queries with auditability. Merchants (companies) post transactions—charges, refunds, payouts—and the ledger serves current and point-in-time balances, statements, and histories. Think of the internal ledgers behind Stripe, Adyen, or PayPal that ensure financial correctness at scale. Interviewers ask this because a ledger stresses the hardest parts of backend design: strong correctness, idempotency under retries, concurrency on hot accounts, immutable audit trails, and scalable read/write paths. They want to see you choose data models and consistency guarantees that keep money accurate while still delivering low-latency queries and high throughput. Expect to discuss double-entry modeling, contention control, materialized balances, and how to evolve the system safely.
Common Functional Requirements
Most candidates end up covering this set of core functionalities
Users should be able to create and manage accounts for companies (and optional sub-accounts), including currency and basic metadata.
Users should be able to record idempotent, atomic double-entry transactions that move funds between accounts with effective timestamps and metadata.
Users should be able to query current and point-in-time balances for one or more accounts, optionally filtered by currency.
Users should be able to list and filter transaction history (by time range, type, account) for reconciliation and auditing.
Common Deep Dives
Common follow-up questions interviewers like to ask for this question
In financial systems, duplicate or partial postings are unacceptable. Interviewers look for concrete mechanisms that make writes atomic and deduplicated across network retries and service restarts. - Use an idempotency key per client request (e.g., merchant_id + client_txn_id) and enforce uniqueness with a durable constraint so that retries return the original result. - Model transactions as immutable, balanced journal entries that write both sides atomically; consider a single append with all legs, not two separate writes. - If you introduce a log/stream, consider an outbox pattern and exactly-once processing semantics (or at-least-once with dedupe by key + sequence) so consumers never double-apply entries.
Balance queries dominate traffic and must be fast, but computing them by summing all history does not scale. Show how you separate the source of truth from read-optimized views. - Maintain per-account running balances with monotonic sequence numbers, plus periodic snapshots to support point-in-time lookups; verify version on reads to avoid stale caches. - Build a materialized view (e.g., aggregated by account, currency, day) and use it for current balances and common reporting; fall back to the ledger for precise as-of corrections. - Cache hot balances in a fast store, but include a freshness or version check (last_applied_seq) so you can invalidate or reconcile safely.
Contention is common when many transactions hit the same account. Interviewers expect a strategy that preserves order and correctness without serializing the entire system. - Partition data and work by account_id; serialize operations per account via a keyed queue or partitioned stream so only that account's updates are ordered. - Use optimistic concurrency with a version field (or sequence) on the running balance row; retries on conflict keep correctness while allowing parallelism across accounts. - Avoid global transactions or cross-partition locks; structure transfers as a single atomic append that includes both legs and an account-scoped ordering token.
Financial ledgers require immutability and traceability. Fixes should be expressed as new entries, not edits, while preserving clear lineage for auditors and engineers. - Make ledger entries append-only; implement corrections as reversing entries (and, if needed, re-posts) with links to the original transaction id. - Distinguish created_at from effective_at to support backdated entries and accurate point-in-time balances; reconcile via replays or differential adjustments. - Store rich metadata (who, why, source system) and maintain a consistent workflow for manual adjustments with review and access controls.
Relevant Patterns
Relevant patterns that you should know for this question
Hot accounts and high-frequency merchants create write contention. You must serialize updates per account, use optimistic concurrency, and avoid global locks to keep throughput while guaranteeing correctness.
Balance and statement queries far outnumber writes. Pre-aggregations, snapshots, and read-optimized materialized views are essential to meet low-latency SLAs for current and point-in-time balances.
A ledger is an append-only system that can see very high write rates. Partitioning by account, batched appends, and ordered ingestion paths are necessary to sustain throughput without sacrificing atomicity.
Relevant Technologies
Relevant technologies that could be used to solve this question
A relational database with strong ACID transactions, unique constraints, and serializable isolation is a natural fit for double-entry ledgers, idempotency enforcement, and atomic multi-row writes.
Similar Problems to Practice
Related problems to practice for this question
Both require atomic, idempotent posting of financial events, double-entry modeling, and strict auditability, plus read-optimized paths for balances and statements.
Brokerage platforms maintain internal ledgers for positions and cash balances, emphasizing immutability, point-in-time queries, and high-throughput event ingestion.
High-contention inventory updates mirror hot-account contention in ledgers; both demand careful concurrency control, idempotency, and low-latency read paths on derived state.
Red Flags to Avoid
Common mistakes that can sink candidates in an interview
Question Timeline
See when this question was last asked and where, including any notes left by other candidates.
Early August, 2025
Stripe
Senior
Mid July, 2025
Stripe
Senior
45-min, design ledger to handle recording transactions for merchants and querying account balances
Mid April, 2025
Stripe
Mid-level
Your account is free and you can post anonymously if you choose.