Lesson 13 of 16
45. Design a Payment System (Stripe / UPI)

Score yourself

3 min read+10 XP

Score yourself

Give yourself 0, 1 or 2 points per row.

Area0 points1 point2 points
RequirementsStarted drawingPay and refundExactly-once effect, unknown outcomes, auditability and card data agreed
EstimatesNoneNumbers, not used laterModerate throughput, ledger growth and retention drove SQL, sharding and partitioning
API and dataSkippedAPI onlyIdempotency keys, integer amounts, intents, attempts, balanced ledger lines, outbox
High-level designCall the bank, update a balanceEngine + DBIntent → attempt → ledger + outbox, callbacks, status checks, reconciliation walked
Deep diveHand-wavedOne topicIdempotency at every hop, double-entry, pending + reconciliation, webhooks or consistency done properly
Trade-offsNone namedNamed when askedRaised unprompted (pending vs guessing, strong vs eventual, hot accounts)
CommunicationLong silencesMostly clearThought out loud, checked in, managed time

12 to 14: strong hire signal. 8 to 11: solid, polish the weak rows. Under 8: redo the round in a week, timer on.

The bar: fresher vs SDE-2

FresherSDE-2
Double charges"Check if already paid"Idempotency keys at every hop, unique ledger transaction IDs
Money recordsBalance columnDouble-entry, append-only, derived balances, integer amounts
Unknown outcomesRetry or failPending state, status checks, callbacks, reconciliation
NotificationsCallback URLSigned, retried, de-duplicated webhooks; server proof over browser redirects
ConsistencyOne big transactionState + ledger + outbox together; eventual elsewhere; sagas across shards

Common mistakes

  • Treating a timeout as a failure (or as a success).
  • A mutable balance column with no ledger behind it.
  • Floating-point money.
  • Trusting the browser redirect as proof of payment.
  • Editing or deleting past ledger entries instead of reversing them.
  • No reconciliation, so lost callbacks are never noticed.

Quick check

Five questions on this chapter. Pick an answer, then check it.

quiz