Katkat

Design a banking ledger for deposits/withdrawals

AirbnbSoftware Engineer · Technical Screen

Last updated

This question tests your ability to design a robust database schema and service logic for a banking system, focusing on data integrity, transaction atomicity, and handling high-concurrency balance updates.

Banking Ledger Design

Design a backend service to support account deposits and withdrawals. A user should be able to view their current balance and a historical list of their transactions.

Requirements

  1. Atomic Transactions: Balance updates must be consistent. A withdrawal should fail if it results in a negative balance.
  2. Concurrency: Multiple concurrent operations on the same account must not cause race conditions (e.g., "lost updates").
  3. Idempotency: Requests from a client might be retried due to network issues; the system must ensure a specific transaction is not processed twice.
  4. Audit Trail: Every change to an account balance must be logged as an immutable transaction record.

Tasks

  1. Define the database schema (tables for accounts and transactions).
  2. Describe the logic for a withdraw(account_id, amount, idempotency_key) function.
  3. Explain how you handle monetary precision (e.g., avoiding floating-point errors).

Constraints

  • Assume 10,000+ requests per second.
  • All money values must be represented accurately.

Example

  • Input: withdraw(acc_123, 50.00, 'req_abc')
  • If acc_123 has 100.00, it becomes 50.00, and a record is inserted into transactions with status SUCCESS.
  • A subsequent retry with req_abc should return the cached result of the first call without deducting 50.00 again.

Hints

Hint 1

Use a dedicated 'transactions' table where the account balance is derived from the sum of all transaction records or a 'current_balance' field updated within a database transaction.

Hint 2

Store monetary amounts as integers in the smallest currency unit (e.g., cents) to avoid IEEE 754 floating-point inaccuracies.

Hint 3

Implement idempotency by storing the 'idempotency_key' in a unique constraint column in the transactions table to prevent duplicate inserts.

Follow-up questions

  • How would you handle a distributed system where the transaction log grows into the billions of rows?
  • What changes would be necessary to support multi-currency accounts (e.g., holding both USD and EUR)?
  • How can you improve performance if one specific 'hot' account is receiving thousands of transactions per second?