Introduction

In this article, we walk through the design of a modern, scalable e-commerce system.
The goal: to create an architecture that is resilient, high-performing, extensible, and can handle the realities of a busy, dynamic online store.

Our task is to design:

  • Product Management (browse/search/add products)
  • Inventory Control (manage stock levels)
  • Order Processing (cart, checkout)
  • Payment Processing (external credit card integration)
  • Shipping Management (select address, prepare shipment)

We use Domain-Driven Design (DDD) principles, Event-Driven Architecture (EDA), and a microservices approach for decoupling.

Let’s dive into the journey!

System Design: Step-by-Step

1. Defining Bounded Contexts

We divide our system into bounded contexts for clear responsibility separation:

Each service owns its own database and communicates via asynchronous events using a message broker like Kafka.

2. Modeling Aggregates and Entities

Following DDD, we model our key entities:

3. Event-Driven Checkout Flow

We implement a choreographed event-driven flow during checkout:

This flow allows services to scale independently while ensuring a resilient checkout process.

4. Commands, Events, and Event Payloads

Here are some sample event payloads:

OrderCheckoutStarted

StockReserved

PaymentSucceeded

5. Database Schema Highlights

Each service manages its own tables:

Product Service – products Table

Searchable by name & description. Recommend indexing name, description for faster search.

Inventory Service – inventory_items Table

Handle stock updates atomically. available_quantity must decrease when reserved.

Order Service – orders Table

Order Service – order_items Table

Payment Service – payments Table

Shipping Service – shipments Table

And so on for payments and shipments.

Use UUIDs everywhere for easy service boundaries (no clashing PKs).

Add indexes on product_id, order_id, customer_id for fast joins.

Partition orders table if traffic is huge (e.g., by creation year).

Use JSONB for flexible address storage (avoids needing a separate Address table).

6. Event-Driven Architecture:

Choreography vs Orchestration

Quick Definitions



Example with our E-Commerce Checkout

If Choreography:
  • Order Service emits OrderCheckoutStarted.
  • Inventory Service listens → reserves stock → emits StockReserved.
  • Payment Service listens → initiates payment → emits PaymentSucceeded.
  • Shipping Service listens → ships the order.
  • NO master controller.
    Each service only listens and reacts.

✅ Pros:

  • Low coupling between services.
  • System is very scalable.
  • Easy to add new behaviors (new services can listen to events).

❌ Cons:

  • Harder to debug.
  • No central place that knows the whole flow.
  • Failure recovery (e.g., retry stock reservation) is complex.

If Orchestration:
  • Order Service becomes the orchestrator.
  • It:
    1. Calls InventoryService.ReserveStock()
    2. If success, calls PaymentService.InitiatePayment()
    3. If success, calls ShippingService.InitiateShipment()
  • Synchronous or callback-based communication.

✅ Pros:

  • Easy to debug (Order Service sees everything).
  • Central control over flow and retries.
  • Explicit logic for recovery paths.

❌ Cons:

  • Tighter coupling between services.
  • Scalability bottleneck if OrderService is overloaded.
  • Harder to evolve new flows dynamically.

7. Why Choreography (Not Orchestration)?

In our case, choreography was better because:

  • Low coupling = easier to evolve services
  • High scalability (no single orchestrator bottleneck)
  • Simpler for distributed transactions

Recovery is handled using:

  • Dead letter queues (DLQ)
  • Retry mechanisms
  • Idempotent processing

8. Realistic Timeline: Checkout to Shipment

Total time to confirm checkout: ~850ms to 1.2 seconds.
Smooth, real-time user experience.

Conclusion

Through careful domain modeling, event-driven design, and clean service separation,
we created an e-commerce architecture that is:

  • Highly scalable
  • Resilient to failures
  • Extendable for new features
  • Aligned with real-world latency expectations

This approach isn’t just theoretical — it’s the foundation for modern platforms like Amazon, Shopify, and Walmart’s e-commerce engines.

Event-Driven + Domain-Driven = Futureproof Architecture.


Leave a Reply

Your email address will not be published. Required fields are marked *