Practice/Stripe/Ledger System
Ledger System
CodingMust
Problem Statement
Design a ledger service for a payments platform that tracks all financial activity on behalf of merchants. When a payment platform processes transactions for online businesses, it needs a reliable bookkeeping system to record every movement of money and enable accurate balance calculations.
Consider a typical e-commerce scenario: an online store uses a payment platform to collect money from customers. The platform receives payments throughout the day and periodically settles with the merchant. A ledger system serves as the source of truth for all these financial movements -- recording when money is collected from customers, when fees are deducted, and when funds are paid out to merchants. The system must guarantee that no money is lost, double-counted, or silently dropped, because financial data demands the highest level of correctness.
Key Requirements
Functional
- Record financial transactions -- track when money is collected from customers or paid out to merchants, with a unique transaction ID, amount, type, and timestamp
- Query account balances -- calculate the current balance for any merchant at any time, including breakdowns of available vs. pending funds
- Double-entry bookkeeping -- every transaction should have corresponding debit and credit entries across accounts to ensure the books always balance
- Immutable audit trail -- ledger entries are append-only; corrections are modeled as new compensating entries, never as mutations
Non-Functional
- Strong consistency -- financial data requires that transactions are never lost or double-counted; use serializable isolation or equivalent guarantees
- Idempotency -- duplicate transaction submissions must be safely rejected using a unique transaction ID
- High throughput -- handle millions of transactions per day while maintaining query performance for balance lookups
- Durability -- committed transactions must survive any single-node failure; use synchronous replication
What Interviewers Focus On
Based on real interview experiences, these are the areas interviewers probe most deeply:
1. Data Model and Double-Entry Bookkeeping (Most Emphasized)
Interviewers want to see how you model credits and debits. The core insight is that every financial movement should be represented as a pair of entries that sum to zero.
Hints to consider:
- Each transaction creates two ledger entries: a debit on one account and a credit on another
- For a customer payment: debit the customer's account (money leaves), credit the merchant's account (money arrives)
- Model accounts explicitly: merchant settlement account, platform fee account, customer payment account
- The sum of all entries across all accounts should always be zero (conservation of money)
2. Balance Calculation Strategy
Do you compute balances on-the-fly by summing all entries, or maintain running totals? This tradeoff is a core discussion point.
Hints to consider:
- On-the-fly summation is simple and always correct but slow at scale (scanning millions of rows)
- Materialized running balances are fast to query but require careful handling of concurrent updates
- A hybrid approach: maintain a snapshot balance at periodic checkpoints, then sum only recent entries
- Use database-level locks or optimistic concurrency control when updating running balances
3. Idempotency and Exactly-Once Semantics
How do you handle duplicate transaction submissions? This is critical in a distributed payments environment where retries are common.
Hints to consider:
- Use the transaction ID as a unique constraint in the database; reject duplicates at the DB level
- Return the same response for duplicate submissions (idempotent response)
- Consider a separate idempotency key table with expiration for API-level deduplication
- Handle the case where a transaction was partially written (e.g., debit recorded but credit failed) using database transactions
4. Concurrency and Isolation
How do you handle concurrent transactions on the same merchant account without corrupting balances?
Hints to consider:
- Serializable isolation level for critical balance-modifying transactions
- Optimistic locking with version numbers on balance rows
SELECT FOR UPDATE to lock the merchant's balance row during a transaction
- Consider the throughput implications: serializable isolation reduces concurrency on hot accounts
5. Historical Queries and Reconciliation
Interviewers may extend the problem to ask about time-travel queries and reconciliation with external systems.
Hints to consider:
- Point-in-time balance queries: "What was this merchant's balance at 3pm yesterday?"
- Use the append-only ledger entries with timestamps to reconstruct historical state
- Reconciliation jobs that compare ledger balances against bank account statements
- Periodic snapshots to speed up historical balance reconstruction