Design an E-Commerce Order Management System
Fast recall
Quick revision
Core answer
CREATED → INVENTORY_RESERVED → PAYMENT_CONFIRMED → PICKING → PACKED → SHIPPED → DELIVERED) with event-sourced transitions for full auditability. Coordinate the cross-service flow with an orchestrated Saga — explicit compensating actions per step rather than implicit choreography. Reserve inventory optimistically with a TTL to handle abandoned checkouts; gate the reservation by an atomic SQL guard that prevents overselling. Use the transactional outbox pattern for reliable event publishing across Order, Inventory, Payment, Fulfillment, and Notification services. CQRS: writes go to PostgreSQL, reads of complex order queries go to Elasticsearch.Saga pattern (orchestration vs choreography), inventory reservation under contention, distributed-transaction-free coordination, event sourcing, and read/write separation at scale.
Single 2PC distributed transaction across services (locks under flash-sale load), or implicit choreography that becomes unmaintainable at 7 services.
Justify orchestration over choreography for debuggability, TTL-based optimistic reservation with atomic SQL guard, the outbox pattern for reliable cross-service events, and Redis pre-decrement for flash-sale hot SKUs.
Interview-ready guide
Interview answer
Clarifying questions I'd ask first
- Single warehouse or multi-warehouse with split shipments?
- Marketplace (multi-seller) or single seller?
- Returns and refunds in scope?
- Cancellation allowed before/after shipping?
- Inventory consistency — strict (never oversell) or eventual (manual refund)?
- Audit retention requirements?
Assumptions for this design
1.5M orders/day average, 10K/sec at peak during Prime Day. Single seller, multi-warehouse, split shipments allowed. Strict inventory consistency — never oversell. Saga orchestration. 5-second p99 for the order API. 7-year audit retention.
Quick capacity check
- 17 orders/sec average, 10K/sec peak; ~70K cross-service calls/sec at peak
- Order-status reads at ~100K QPS — needs CQRS
- Storage: ~7.5 GB/day of orders, 15 GB/day of events; 2.7 TB/year primary
- Flash-sale SKU at 10K concurrent buyers needs Redis pre-decrement (PostgreSQL row-lock collapses)
The order state machine and event sourcing
- Explicit state machine: CREATED → INVENTORY_RESERVED → PAYMENT_CONFIRMED → PICKING → PACKED → SHIPPED → DELIVERED, with CANCELLED and REFUNDED as terminal states
- Each transition validated against the current state — SHIPPED can't go back to PICKING
- Append-only
order_eventstable is the audit canonical; theorderstable is a materialized projection for fast reads - Optimistic concurrency on
versioncolumn prevents simultaneous-transition races (customer cancel vs warehouse ship)
Saga — orchestration over choreography
- With 7 services, implicit event chains are unmaintainable
- Orchestrator is one method that calls each service in sequence with explicit compensations on failure
- Readable in one place, testable with standard unit tests, debuggable with one log stream
- Saga state persisted after each step — watchdog resumes after orchestrator crashes
- Each downstream call is idempotent on
order_idso resumption doesn't double-act
The orchestrator flow — step by step
- 1OrderService.create → status CREATED, save saga state
- 2inventory.reserve(orderId, items, 30 min TTL) → INVENTORY_RESERVED; on failure, cancel
- 3fraud.score → if high risk, release inventory and cancel
- 4payment.charge → PAYMENT_CONFIRMED; on failure, release inventory and cancel
- 5fulfillment.assignWarehouse, shipping.createLabel, notifications.sendConfirmation
- 6saga state COMPLETED, return success
Inventory — normal vs flash sale
- Normal SKU: atomic SQL guard
UPDATE inventory SET reserved = reserved + qty WHERE sku = ? AND total - reserved >= qty. Zero rows affected = out of stock - Reservation rows have TTL (30 min) — abandoned checkouts release stock automatically via background sweeper
- Flash-sale SKU: Redis pre-decrement of a counter loaded at sale start. Redis handles 100K decrements/sec on a single key; PostgreSQL would crawl at single-digit successful TPS
- DB reservation created asynchronously after Redis confirms availability; if DB write fails, restore Redis counter
Cross-service consistency — outbox + CDC + CQRS
- Outbox table written in the same transaction as the order update; eliminates the dual-write problem
- Debezium CDC streams the outbox to Kafka with near-zero lag
- Order writes go to PostgreSQL; Kafka consumer maintains an Elasticsearch index for diverse read queries
- Single-order detail with event history: PostgreSQL; list/search/filter: ES
- ES lags ~1-2 seconds; just-after-write GETs go to PostgreSQL
LLD — clean abstractions
OrderStateMachine— the legal-transition table, queried by both the API ("can this be cancelled?") and the serviceOrderRepositoryinterface (PostgresOrderRepository impl)OrderSagaOrchestratorwithSagaStateStore— saga survival across orchestrator restarts is non-negotiable- One client interface per downstream service (
InventoryClient,PaymentClient, etc.) for mocking and circuit breakers - Idempotency at every downstream call keyed by
order_id
Failure handling
- Orchestrator crash: saga state persisted; watchdog resumes from last successful step
- Downstream service down: fast-fail with circuit breaker; saga compensates
- Long-running payment (3D Secure): saga moves to WAITING_FOR_PAYMENT, returns 202 Accepted, resumes on webhook
- Cancel race during PICKING: optimistic version check; only one transition wins; loser sees 409 and offered return-after-delivery
- Reservation TTL expires: sweeper releases; saga retry on confirm sees ReservationExpired and re-reserves or cancels
Production extras
- Authentication on every API call; customers see only their orders
- Fraud service scores every order pre-payment; high-risk goes to FRAUD_REVIEW
- Velocity limits per customer and per IP/device
- PII encrypted at rest (addresses, tokenized cards)
- Soft delete only — audit retention 7 years
- Distributed tracing across the 7-service flow with one correlation ID
At 10× scale
- Sharded order DB by
customer_idhash - Per-region active-active inventory with CRDTs for normal SKUs, centralized for flash sales
- Replace orchestrator with Temporal/Cadence workflow engine
- Streaming-first events with downstream subscribers
Recommendation
Explicit order state machine with event sourcing, orchestrated Saga with persisted state and explicit compensations, atomic SQL guards plus Redis pre-decrement for flash-sale inventory, optimistic concurrency for race-free transitions, outbox + CDC for reliable cross-service events, and CQRS with Elasticsearch for the diverse read patterns — the same shape Amazon, Shopify, and Flipkart run for order management at scale.
Design an E-Commerce Order Management System
Direct Answer
Model the order as an explicit state machine (CREATED → INVENTORY_RESERVED → PAYMENT_CONFIRMED → PICKING → PACKED → SHIPPED → DELIVERED) with event-sourced transitions for full auditability. Coordinate the cross-service flow with an orchestrated Saga — explicit compensating actions per step rather than implicit choreography. Reserve inventory optimistically with a TTL to handle abandoned checkouts; gate the reservation by an atomic SQL guard that prevents overselling. Use the transactional outbox pattern for reliable event publishing across Order, Inventory, Payment, Fulfillment, and Notification services. CQRS: writes go to PostgreSQL, reads of complex order queries go to Elasticsearch.
Common Mistakes & Pitfalls
Single 2PC distributed transaction across services (locks under flash-sale load), or implicit choreography that becomes unmaintainable at 7 services.
Check your understanding
Answer these without looking back at the article.
- How would you handle a flash sale where 100,000 users try to buy 100 units simultaneously — walk through the inventory contention path end-to-end.
- How do you implement the return/refund flow as a sub-saga without conflating it with the main place-order saga?
- How would you design the system to support multi-warehouse split shipments (one order, two packages from different warehouses)?
- Compare orchestrated Saga vs choreography for this design and articulate when each wins.
Related interview prep categories
1Want a guided curriculum order?
These modules are also sequenced in our flagship backend interview track — open it when you prefer an ordered path instead of browsing by topic.