Practice/Uber/Design a Transaction Clearing System
Design a Transaction Clearing System
System DesignMust
Problem Statement
Design a financial clearing house system that processes transactions between parties and generates end-of-day reports showing credit/debit amounts for each party. The system must handle millions of transactions daily across thousands of parties with zero transaction loss to ensure financial accuracy.
A clearing house is a financial back-office system that ingests transactions between parties, posts them to ledgers, and produces end-of-day statements showing what each party should be credited or debited. The invisible infrastructure ensures every transfer is accounted for, balances add up, and the books can be closed each day without losing a single cent.
Interviewers at Uber ask this to test if you can design for correctness at scale: immutable ledgers, exactly-once effects, ordering, reconciliation, and batch cutoffs. They also probe whether you can balance high write throughput with strong auditability, handle replays and backfills, and produce reliable end-of-day outputs under real-world failure modes.
Key Requirements
Functional
- Transaction submission -- users submit transactions between two parties with amount, currency, and a unique reference
- Running position -- users view the status of submitted transactions and their running net position during the day
- End-of-day reports -- users receive reports summarizing credits, debits, and net settlements per party
- Corrections -- users request reversals or adjustments that are tracked and reflected in subsequent reports
Non-Functional
- Scalability -- handle millions of transactions per day with thousands of active parties
- Reliability -- zero transaction loss; tolerate node failures without data inconsistency
- Latency -- transaction submission acknowledged within 200 ms; end-of-day reports generated within minutes of cutoff
- Consistency -- strong consistency for ledger entries; exactly-once processing semantics for financial correctness
What Interviewers Focus On
Based on real interview experiences at Uber, these are the areas interviewers probe most deeply:
1. Immutable Ledger and Double-Entry Design
Mutating balances in place prevents auditability and makes reconciliation impossible. Interviewers expect an append-only, double-entry approach.
Hints to consider:
- Model every transaction as two ledger entries: a credit to one party and a debit to the other
- Make ledger entries immutable and append-only; corrections are new entries (reversals), not mutations
- Use a unique transaction reference (idempotency key) to prevent duplicate posting
- Maintain running balances as materialized views computed from the ledger entries, not as mutable counters
2. Exactly-Once Processing and Idempotency
Networks and consumers fail, creating duplicates. Without deduplication, you will double-post transactions or drop them.
Hints to consider:
- Accept client-provided idempotency keys and deduplicate at the ingestion layer using Redis or database constraints
- Use Kafka with idempotent producers for durable, ordered ingestion
- Process transactions within database transactions: check for duplicate, insert ledger entries, and update materialized balances atomically
- Design the entire pipeline to be replay-safe: re-processing an event produces the same state
3. Partitioning and Contention Management
Some parties are hot (many transactions). Global locks would destroy throughput.
Hints to consider:
- Partition by party/account ID so that transactions affecting the same party are processed sequentially within a partition
- Use single-writer-per-key semantics: one consumer handles all transactions for a given party
- Avoid cross-partition transactions; if a transaction involves two parties, post to each party's ledger independently within a saga
- Use append-only inserts (not read-modify-write) to minimize lock contention
4. End-of-Day Cutoff and Report Generation
Defining "end of day" in a distributed system with in-flight transactions is non-trivial. Interviewers look for a clean cutoff mechanism.
Hints to consider:
- Define a cutoff timestamp; transactions submitted after cutoff roll into the next day
- Drain all in-flight messages from Kafka before starting report generation (wait for consumer lag to reach zero)
- Generate reports by scanning ledger entries for the day, grouped by party, computing net positions
- Store reports as immutable artifacts (S3) with checksums for auditability
- Support late-arriving transactions through adjustment entries in the next day's report