Revision sheet
Design e-commerce checkout.
The six things worth holding in your head the night before. Everything else is on the full page.
The opening move — minute one
“Checkout is a promise made before the money moves. At 10M orders a day that’s only ~120 a second — so this isn’t a throughput problem, it’s a promise problem: I reserve stock with a TTL, authorize — not capture — and confirm only when both hold. Oversell is the failure I design against; expiry is the safety net that cleans up everything else.”
The order state machine
PLACED → RESERVED → CONFIRMED → SHIPPED
PAYMENT_FAILED (from RESERVED: decline — keep the hold for a retry until the TTL) · EXPIRED (TTL passed — the sweeper returns the stock) · CANCELLED (pre-ship: void the auth — free, because capture waited)
Must-haves
- Prevents oversell with an atomic conditional reserve — names the TOCTOU race in check-then-decrement and puts the check in the same statement as the write.
- Reserves at place-order (not add-to-cart) with a TTL, a sweeper, and an explicit abandonment argument (~70% of carts walk).
- Orchestrates payment as authorize-at-checkout, capture-at-ship — sequenced reserve → authorize → confirm so every pre-ship failure is a free void — with idempotent order placement on top.
- Does the arithmetic (10M/day ≈ 120 TPS), concludes one ACID database over reflex-sharding, and splits browse (cached, stale-OK) from the reserve path (strongly consistent).
Red flags
- Read-then-write stock math anywhere on the reserve path — the oversell is not hypothetical; it’s two concurrent requests away.
- Capture at checkout, or any charge that can exist without a confirmed order (no orphan sweep).
- Reservations without expiry — every abandoned checkout leaks a unit until the storefront lies.
The 7 trap claims — each one is wrong
- “reserve the stock when the item goes into the cart”
- “check the stock, then decrement it”
- “capture the payment at checkout”
- “charge whatever price the cart shows”
- “eventual consistency is fine — it’s just shopping”
- “we’ll handle the flash sale by autoscaling”
- “publish “order placed” to the bus, then write the order”
The L4 lines — what depth sounds like
Inventory Reservation & Oversell
Chooses between row locks, atomic counters, and per-SKU serialization by contention profile, and prices false sold-outs against oversell when the mechanisms trade off
Reservation Lifecycle & TTL
Handles the TTL-vs-payment race: bounded extension while payment is in flight, re-reserve at confirm, void on failure, and reservation-age alerts as stuck-saga detection
Payment Orchestration
Reasons about the irreversibility ladder (void vs refund vs shipped goods), auth expiry against warehouse backlog (re-auth before ship), and the webhook-vs-redirect race as first-class design
Flash-Sale Contention
Prices the alternatives (bucketed counts vs serialized per-SKU queues vs counter-plus-truth), reconciles counter-vs-database divergence, and designs fairness and bot pressure at the admission layer