DDSA Solutions
Case Study6 min read·

Design an E-Commerce Platform (Amazon)

System design for online shopping: product catalog, inventory, cart, checkout, order fulfillment, and scaling browse vs buy paths for interviews.

E-commerce interviews blend read-heavy catalog browsing with write-heavy checkout that must not oversell inventory. Amazon-scale sounds scary; mid-level loops usually want product search, cart, order placement, and how browse and buy paths differ. Use the framework and connect to payments, search, and distributed cache.

Requirements

Functional

  • Browse products by category; search by keyword; view detail page.
  • Add to cart; update quantity; checkout with shipping address.
  • Place order; decrement inventory; charge payment.
  • Order history and order status tracking.

Non-functional

  • 100M products, 50M DAU, Black Friday 10× traffic spike.
  • Browse p99 under 300 ms; checkout must not oversell (inventory accuracy).
  • Cart can be anonymous (session) or logged-in.
  • Eventual consistency OK for product reviews; not for inventory at checkout.

Scope marketplace vs retail

Marketplace (third-party sellers) adds seller inventory partitions and split payouts. Retail-only (Amazon 1P) simplifies to one inventory table per SKU. Ask which model to design.

High-level architecture

ComponentRole
Product catalog serviceSKU metadata, images, price (read-heavy)
Search (search engine)Elasticsearch index of catalog
Cart service (Redis)session_id / user_id → line items
Inventory serviceAvailable quantity per SKU; reserve on checkout
Order serviceCreate order, orchestrate payment + fulfillment
Payment serviceCharge card (payment design)
NotificationOrder confirmation email

Browse path (read-heavy)

Product detail served from cache — CDN for images, Redis for JSON catalog rows. Category browse uses denormalized lists or search filters. Price may change — short TTL (60 sec) or version field on cache entry. Load balancer scales stateless API tier horizontally. Database: PostgreSQL or Dynamo for catalog; sharding by product_id at billion-SKU scale.

Cart

Cart is ephemeral: `cart:{user_id}` hash in Redis — `sku_id → { qty, price_snapshot }`. No inventory reservation in cart (Amazon model) — reservation happens at checkout. Anonymous carts keyed by session cookie; merge on login. TTL 30 days for logged-in users. Cart writes are cheap; losing Redis loses carts — acceptable vs losing orders.

Checkout and inventory

  1. POST /checkout — validate cart SKUs still active and priced.
  2. Inventory: `UPDATE inventory SET reserved = reserved + ? WHERE sku_id = ? AND quantity - reserved >= ?` in transaction.
  3. If any SKU fails, abort entire checkout (all-or-nothing).
  4. Create order row status=PENDING_PAYMENT; call payment authorize.
  5. On payment success: order=CONFIRMED, reserved→sold; on failure: release reservation.
  6. Publish order event to Kafka for warehouse fulfillment.

Overselling is the failure mode interviewers probe. Row-level lock or atomic UPDATE on inventory — same pattern as ticket booking. Do not cache inventory counts for checkout writes.

Order service and sagas

Checkout spans inventory, payment, and shipping label — classic saga. Happy path: single orchestrated flow. Payment timeout: compensating transaction releases inventory reservation. Use idempotency key on `POST /checkout` so retry does not double-order (unique IDs). Order state machine: PENDING_PAYMENT → CONFIRMED → SHIPPED → DELIVERED.

Search and recommendations

Catalog search mirrors search engine design: inverted index on title, brand, attributes. Autocomplete on product names (typeahead). Recommendations ("customers also bought") precomputed offline into Redis feature store — not on checkout critical path.

Advertisement

Data model sketch

  • products: sku_id, title, description, price_cents, category_id
  • inventory: sku_id, warehouse_id, quantity, reserved
  • orders: order_id, user_id, status, total, payment_id, created_at
  • order_items: order_id, sku_id, qty, price_at_purchase
  • carts: Redis only — not durable SQL

Capacity estimation

100M SKUs × 2 KB metadata ≈ 200 GB catalog — fits sharded SQL with aggressive caching. 1M orders/day ≈ 12 order writes/sec average (500/sec peak on Black Friday) — modest for PostgreSQL. Browse 50M DAU × 20 page views × 5 KB ≈ 5 TB/day CDN traffic if uncached — cache product pages at edge. Black Friday: queue checkout if inventory service saturates (rate limiter).

Failure modes

FailureMitigation
Payment charged but order not savedReconciliation job; idempotent order create by payment_id
Inventory reserved, payment failsTTL on reservation; sweeper releases stock
Stale price in cartRe-price at checkout; show user delta
Hot SKU flash saleQueue + per-user purchase limit; same as ticketing
Search index lagNew products hidden until indexed; OK for minutes

API sketch

  • GET /products/{sku} — detail (cached)
  • GET /search?q= — Elasticsearch
  • POST /cart/items — add SKU
  • POST /checkout — idempotency-key header required
  • GET /orders/{id} — status

Sample opening (first three minutes)

Interviewer: "Design Amazon." You: "I will separate browse — cached catalog and search — from checkout — transactional inventory and payment. Cart lives in Redis without reservation. Checkout atomically reserves stock, charges payment with idempotency, and emits fulfillment events. I will clarify marketplace scope and estimate read vs write QPS."

Warehouse fulfillment (async)

After order CONFIRMED, warehouse service consumes Kafka event, picks nearest fulfillment centre with stock, prints label, updates tracking. User sees SHIPPED via polling or push notification. Returns flow increments inventory when item received — separate reverse saga. None of this blocks checkout latency.

Reviews and ratings

Product reviews are write-rare, read-often — eventual consistency fine. Aggregate rating updated async from review stream; detail page shows cached 4.3 stars with minutes of lag. Do not couple review writes to purchase transaction.

What to say in the last five minutes

Close with: "Cached catalog and Elasticsearch for browse, Redis cart, SQL inventory reservation at checkout, idempotent payment, Kafka to warehouse." Draw the read/write split on the board.

Mock interview checklist

  1. Split read path (cache, CDN, search) from write path (inventory, orders).
  2. Explained cart in Redis vs inventory in SQL.
  3. Described atomic inventory decrement / reservation.
  4. Mentioned idempotent checkout and payment saga.
  5. Addressed flash sale / hot SKU contention.

Closing summary

E-commerce is two systems glued together: a fast catalog and a careful checkout. Nail inventory atomicity and payment idempotency — everything else is caching and search you have already practised on this site.

More in this series