Design an e-commerce checkout system
Checkout is where money and stock meet. We design the cart, stock reservation, order flow and payment so nothing is oversold or charged twice.

Goal: turn a shopping cart into a paid, confirmed order, without overselling stock or charging twice.
Requirements
- Cart that survives refresh and device change.
- Correct price, discount, tax and shipping.
- Stock must not be oversold.
- Payment with retries and failure handling.
- A clear order status and confirmation.
Components
- Cart service: stored in Redis or a database (guest carts too, merged on login).
- Catalog and pricing: product details and current price.
- Inventory service: stock per item.
- Order service: creates and tracks orders.
- Payment service: talks to a payment provider.
- Notification service: emails and updates.
Checkout steps
- Validate the cart: items exist, prices are current. Recalculate on the server; never trust prices sent by the client.
- Reserve inventory: reduce available stock or place a time-limited hold for the items.
- Create the order as
PENDING_PAYMENTwith an idempotency key. - Payment: redirect or call the provider.
- On success: mark
PAID, confirm the inventory, start fulfilment, send the email. - On failure or timeout: release the reservation and mark
CANCELLED.
Preventing overselling
Use an atomic conditional decrement: UPDATE stock SET qty = qty - ? WHERE sku = ? AND qty >= ?. If no row changes, the item is out of stock. For very hot items, keep stock counters in Redis with atomic operations and reconcile with the database.
Order state machine
CART -> PENDING_PAYMENT -> PAID -> PACKED -> SHIPPED -> DELIVERED, plus CANCELLED and REFUNDED. Only allow valid transitions and make them idempotent.
Payment issues
- Providers use webhooks that can arrive late, twice or out of order. Verify the signature and handle repeats safely.
- A timeout may hide a successful charge. Query the provider for the real status before retrying.
- Store the payment reference with the order for refunds and support.
Consistency across services
Inventory, order and payment are separate. Use a saga with compensations (release stock, refund) and the outbox pattern so that events are not lost between the database write and the message publish.
Other concerns
Coupons that can be used once (atomic check), address and tax rules, fraud checks, abandoned-cart reminders, and keeping the checkout path fast and simple, since every extra step loses buyers.
Takeaway: recompute prices on the server, reserve stock atomically, run an idempotent order state machine, and use sagas for failures.
System Design series, Part 3 (case studies): 13 of 16. Previous: Design a web crawler.


