Designing an e-commerce store (Amazon)
A large online store — catalog and search, carts, the order workflow, and inventory management that must not oversell.
The problem
Design Amazon (the storefront core): browse/search a huge catalog, add to cart, checkout, and place orders — with inventory that must not oversell. It composes many subsystems (search, cart, orders, payments, inventory) into one read-heavy, money- handling marketplace.
Step 1 — Requirements
Functional: browse/search products; product pages; cart; checkout + order; inventory tracking; order history; recommendations; reviews.
Non-functional: read-heavy (browse ≫ buy), low-latency catalog/search, strong consistency for inventory + orders + payment (no overselling, no double-charge), high availability, huge scale (peak events like Prime Day).
Step 2 — Catalog and search
- Catalog — products in a store optimized for reads; denormalized product pages cached + CDN’d (mostly static). Sharded by product id.
- Search — an inverted index (Chapter 4 search) with faceted filters (category, price, brand) and ranking (relevance, popularity, sponsored).
- Recommendations — “customers also bought,” related items (collaborative filtering).
These are the read-heavy surfaces — caching and indexes dominate.
Step 3 — Cart
The cart is per-user, read/write often, must persist across devices and survive sessions:
- Store in a fast KV store (e.g. DynamoDB/Redis), keyed by user; merge guest carts on login.
- Carts are eventually consistent and tolerant — a brief glitch is fine; the price/ availability is re-validated at checkout, not trusted from the cart.
Step 4 — Inventory (don’t oversell — the core consistency problem)
When many buyers grab the last units, you must not sell more than you have:
- Inventory counts in a strongly consistent store; decrement atomically at order
placement (conditional update: decrement only if
available >= qty). - Or reserve stock at checkout (a hold/lease) and confirm on payment, releasing on abandon — the hold pattern from Airbnb.
- High-contention items (a hot deal) → the decrement is the bottleneck; serialize per-SKU or use atomic counters; accept that this path is CP.
Step 5 — The order workflow (a saga)
Checkout coordinates inventory, payment, and fulfillment without one global transaction → a saga (reuse DoorDash):
checkout → reserve inventory → authorize payment → create order
→ capture payment → fulfillment/shipping
(any failure → compensate: release inventory, void/refund)
Idempotent steps + compensations; the order is a durable state machine (placed → paid → shipped → delivered).
Step 6 — Architecture
browse → catalog (cached/CDN) + search index + recommendations
cart → KV store (per user)
checkout → order saga: inventory (CP) + payment + order state machine
fulfillment → warehouse/shipping services (async)
Built as microservices (catalog, cart, order, inventory, payment, fulfillment), each scaled independently — Amazon famously pioneered this.
Trade-offs to raise
- Catalog/search eventually consistent (fast) vs inventory/order strongly consistent (correct). Split by data — most of the site is AP, the money/stock path is CP.
- Atomic decrement-at-order (simple, contention on hot SKUs) vs reserve/hold (better UX, more moving parts).
- Saga (no global txn, compensations) vs distributed transaction.
The interview cue
“Catalog + search index + recommendations are read-heavy, cached/CDN’d, eventually consistent; the cart is a per-user KV store re-validated at checkout; inventory is strongly consistent with atomic decrement / reserve-and-confirm to avoid overselling; checkout is an order saga (inventory + payment + state machine) with compensations; everything is microservices.” Read-heavy catalog + CP inventory + order saga is the answer; implementation next.