Bird
Raised Fist0
Microservicessystem_design~7 mins

Domain-Driven Design (DDD) basics in Microservices - System Design Guide

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Problem Statement
When software systems grow complex, teams often struggle to keep the code aligned with real business needs. This leads to tangled code, unclear responsibilities, and slow feature delivery because developers and domain experts speak different languages.
Solution
Domain-Driven Design solves this by organizing software around the core business concepts and language. It breaks the system into clear domains and subdomains, each with its own model and logic, ensuring developers and business experts share a common understanding. This alignment helps build maintainable, flexible systems that evolve with business changes.
Architecture
User Interface
(Frontend)
Application
Infrastructure
Infrastructure

This diagram shows how DDD structures a system into layers: the user interface, application logic, domain logic with business rules, and infrastructure for technical details. The domain layer is central, representing the core business concepts.

Trade-offs
✓ Pros
Improves communication between developers and business experts by using a shared language.
Keeps business logic isolated, making the system easier to maintain and evolve.
Supports building microservices aligned with business capabilities, improving scalability.
Helps manage complexity by dividing the system into bounded contexts.
✗ Cons
Requires significant upfront collaboration and domain knowledge gathering.
Can add complexity if applied to small or simple systems unnecessarily.
Needs ongoing effort to keep domain models and code synchronized with business changes.
Use DDD when building complex business systems with multiple teams and evolving requirements, especially when microservices need clear boundaries aligned with business domains.
Avoid DDD for simple CRUD applications or projects with very stable, straightforward requirements where the overhead of domain modeling is not justified.
Real World Examples
Amazon
Amazon uses DDD to organize its vast e-commerce platform into bounded contexts like ordering, inventory, and payment, enabling independent teams to develop and scale services aligned with business capabilities.
Netflix
Netflix applies DDD principles to separate concerns like user management, streaming, and recommendations into distinct domains, allowing rapid innovation and scaling of individual services.
Uber
Uber uses DDD to model complex domains such as ride matching, payments, and driver management, helping to keep business logic clear and services decoupled.
Code Example
The before code mixes validation, calculation, and data saving in one method, making it hard to maintain. The after code separates concerns: Order and OrderItem represent the domain model with business logic, OrderRepository handles data persistence, and OrderService coordinates actions. This clear separation follows DDD principles.
Microservices
### Before applying DDD - tangled business logic mixed with data access
class OrderService:
    def create_order(self, user_id, items):
        # Validate items
        if not items:
            raise ValueError("No items")
        # Calculate total
        total = sum(item['price'] * item['qty'] for item in items)
        # Save order directly
        order = {'user_id': user_id, 'items': items, 'total': total}
        database.save(order)
        return order


### After applying DDD - clear domain model and separation

class OrderItem:
    def __init__(self, product_id, price, quantity):
        self.product_id = product_id
        self.price = price
        self.quantity = quantity

    def total_price(self):
        return self.price * self.quantity

class Order:
    def __init__(self, user_id):
        self.user_id = user_id
        self.items = []

    def add_item(self, item: OrderItem):
        self.items.append(item)

    def total(self):
        return sum(item.total_price() for item in self.items)

class OrderRepository:
    def save(self, order: Order):
        # Persist order to database
        pass

class OrderService:
    def __init__(self, repository: OrderRepository):
        self.repository = repository

    def create_order(self, user_id, items_data):
        if not items_data:
            raise ValueError("No items")
        order = Order(user_id)
        for data in items_data:
            item = OrderItem(data['product_id'], data['price'], data['quantity'])
            order.add_item(item)
        self.repository.save(order)
        return order
OutputSuccess
Alternatives
Layered Architecture
Focuses on technical layers (UI, business, data) without explicit domain modeling or bounded contexts.
Use when: Use when the system is simple or domain complexity is low, and clear separation of technical concerns is sufficient.
Event-Driven Architecture
Centers on asynchronous events and messaging rather than domain models and shared language.
Use when: Choose when system needs high scalability and loose coupling, especially for real-time or distributed systems.
Service-Oriented Architecture (SOA)
Focuses on reusable services often aligned with business functions but may lack the deep domain modeling focus of DDD.
Use when: Use when integrating legacy systems or when services need to be shared across multiple applications.
Summary
Domain-Driven Design aligns software structure with business concepts to manage complexity.
It divides systems into bounded contexts with clear domain models and shared language.
DDD improves maintainability and team collaboration, especially in complex microservices architectures.

Practice

(1/5)
1. What is the main purpose of Domain-Driven Design (DDD) in microservices?
easy
A. To align software design closely with business needs
B. To improve database query performance
C. To create user interfaces faster
D. To reduce network latency between services

Solution

  1. Step 1: Understand the goal of DDD

    DDD focuses on modeling software based on the real business domain and its rules.
  2. Step 2: Compare options with DDD goals

    Only aligning software with business needs matches DDD's main purpose.
  3. Final Answer:

    To align software design closely with business needs -> Option A
  4. Quick Check:

    DDD = Align software with business [OK]
Hint: DDD = software matches business needs [OK]
Common Mistakes:
  • Confusing DDD with performance optimization
  • Thinking DDD is about UI or network improvements
  • Assuming DDD is only about coding style
2. Which of the following is a correct way to describe a 'Bounded Context' in DDD?
easy
A. A network protocol used for service communication
B. A database table shared by all microservices
C. A UI component that handles user input
D. A clear boundary within which a domain model applies

Solution

  1. Step 1: Define Bounded Context

    It is a boundary that defines where a particular domain model is valid and consistent.
  2. Step 2: Match options to definition

    Only 'a clear boundary within which a domain model applies' correctly describes a Bounded Context.
  3. Final Answer:

    A clear boundary within which a domain model applies -> Option D
  4. Quick Check:

    Bounded Context = domain model boundary [OK]
Hint: Bounded Context = domain model boundary [OK]
Common Mistakes:
  • Thinking it is a shared database table
  • Confusing it with UI or network concepts
  • Assuming it is a technical infrastructure term
3. Given the following description, which DDD building block is being described?
A unique object with an identity that persists over time and changes state.
medium
A. Value Object
B. Entity
C. Aggregate
D. Repository

Solution

  1. Step 1: Understand the description

    The object has a unique identity and can change state over time.
  2. Step 2: Match description to DDD concepts

    Entities have unique identities and mutable state; value objects do not have identity.
  3. Final Answer:

    Entity -> Option B
  4. Quick Check:

    Unique identity + state = Entity [OK]
Hint: Entity = unique identity and state [OK]
Common Mistakes:
  • Confusing Entity with Value Object
  • Thinking Aggregate is a single object only
  • Mixing Repository with domain objects
4. You have a microservice with a large domain model mixing unrelated concepts. What DDD principle helps fix this?
medium
A. Define clear Bounded Contexts to separate domains
B. Avoid using entities and only use value objects
C. Merge all services into one monolith
D. Use a single aggregate for all entities

Solution

  1. Step 1: Identify the problem

    The domain model is large and mixes unrelated concepts, causing complexity.
  2. Step 2: Apply DDD principle

    Bounded Contexts separate different domain areas to keep models clear and manageable.
  3. Final Answer:

    Define clear Bounded Contexts to separate domains -> Option A
  4. Quick Check:

    Separate domains with Bounded Contexts [OK]
Hint: Separate domains using Bounded Contexts [OK]
Common Mistakes:
  • Trying to use one aggregate for everything
  • Merging services instead of separating
  • Removing entities incorrectly
5. In a microservices system using DDD, which approach best ensures data consistency within a complex domain involving multiple aggregates?
hard
A. Use transactions spanning multiple microservices
B. Store all data in a single shared database
C. Design aggregates as consistency boundaries and use eventual consistency between them
D. Avoid aggregates and use only value objects for all data

Solution

  1. Step 1: Understand consistency in DDD aggregates

    Aggregates define consistency boundaries; transactions should not span multiple aggregates or services.
  2. Step 2: Choose best practice for microservices

    Use eventual consistency and asynchronous communication between aggregates to maintain scalability and reliability.
  3. Final Answer:

    Design aggregates as consistency boundaries and use eventual consistency between them -> Option C
  4. Quick Check:

    Aggregates = consistency boundaries + eventual consistency [OK]
Hint: Aggregates limit transactions; use eventual consistency [OK]
Common Mistakes:
  • Trying distributed transactions across services
  • Using a shared database breaking microservice boundaries
  • Ignoring aggregates and consistency rules