Design a Payment System
Design Stripe or a payment processing backend. The hard problems are idempotency (never charge twice), consistency (money must not appear or disappear), and reconciliation (detecting when distributed systems disagree about what happened).
What you will learn
- Explain why idempotency keys are mandatory in payment systems and how to implement them
- Design a ledger system that maintains double-entry bookkeeping for financial correctness
- Handle partial failures in a distributed payment flow using the Saga pattern
- Build a reconciliation process that detects and corrects disagreements between systems
Payment systems are where correctness is not a quality attribute — it is the product. A bug in a social media feed shows users the wrong post. A bug in a payment system charges a customer twice, loses money, or creates a regulatory incident. The engineering constraints follow directly from that: idempotency is mandatory, consistency must be guaranteed, and every transaction must be auditable and reconcilable.
Functional requirements:
- Accept payments from users (card, bank transfer, wallet)
- Transfer money between accounts (merchant payouts)
- Handle refunds and chargebacks
- Provide payment status and history
Non-functional requirements:
- Exactly-once payment execution — a charge must never happen twice for the same intent
- Durability — no payment record is ever lost, even under failures
- Audit trail — every state change is logged and immutable
- Consistency — account balances must always be correct; no money appears or disappears
- Compliance — PCI DSS (card data), SOC 2, GDPR
Create a free account to read the full chapter — advanced chapters, progress tracking, and quizzes are free with sign-up.