A strategic approach to software development that centers on understanding and modeling the core business domain. Build systems that speak your business language and evolve with your organization.
Most software projects fail not because of technical issues, but because developers and domain experts speak different languages. DDD bridges this gap by putting the domain model at the center of everything.
Domain Driven Design (DDD) was introduced by Eric Evans in his 2003 book. The core philosophy: software should reflect the mental model of the business domain it serves. When code mirrors how domain experts think, it becomes easier to understand, maintain, and evolve.
Invest your best talent and effort in the business areas that differentiate you
Code should directly implement the domain model—no translation layer between design and code
Developers and domain experts use the same terminology everywhere—in code, documentation, and conversation
Large systems are divided into explicit boundaries where each model is consistent and meaningful
DDD shines in complex domains where:
Not everything needs DDD. For simple CRUD apps or straightforward data pipelines, DDD adds unnecessary complexity. Save it for your core domain.
Strategic design is about the big picture: how to organize your system into distinct parts and how those parts relate.
A shared vocabulary used by everyone—developers, product managers, designers, and domain experts—in all communication and code.
UserTransactionCustomerExplicit boundaries within which a particular domain model is defined and applicable. Each context has its own ubiquitous language and model.
The same real-world thing often means different things in different contexts. A "Customer" in Sales is different from a "Customer" in Billing—they have different attributes, behaviors, and rules.
Customer, Lead, Quote, Discount
Order, Shipment, Inventory, Warehouse
Account, Invoice, Payment, Subscription
Each context owns its own "Customer" representation with only the data it needs.
Not all parts of your domain deserve equal investment. Classify subdomains to focus your best effort where it matters most.
What makes you unique. Your competitive advantage.
Necessary but not differentiating. Supports the core.
Commodity. Same for everyone.
How bounded contexts relate to and communicate with each other. Understanding these relationships prevents integration nightmares.
Teams coordinate closely, succeed or fail together
Upstream team provides what downstream needs
Contexts share a small, agreed-upon model subset
Translate external models to protect your domain
Provide a published API for multiple consumers
Downstream adopts upstream's model as-is
Tactical patterns are the building blocks for implementing your domain model in code. Use these within a single bounded context.
Objects with a unique identity that persists over time. An entity is the same entity even if all its attributes change.
Customer(id: "C-123")
// Still same customer even if name/email changesObjects defined by their attributes, not identity. Two value objects with same attributes are equal. Immutable.
Money(100, "USD") === Money(100, "USD")
// Always equal if attributes matchCluster of entities and value objects treated as a single unit. One entity is the "aggregate root"—all access goes through it.
Order (aggregate root)
  ├── OrderLine[]
  ├── ShippingAddress
  └── PaymentInfoSomething significant that happened in the domain. Used for communication between aggregates and bounded contexts.
OrderPlaced(orderId, customerId, total)
PaymentReceived(orderId, amount)Abstraction for retrieving and persisting aggregates. Hides database details from the domain model.
OrderRepository.findById(id)
OrderRepository.save(order)Operations that don't naturally belong to an entity or value object. Stateless operations on domain objects.
PricingService.calculateDiscount(order, customer)
InventoryService.checkAvailability(items)Apply DDD thinking during the Research to Backlog flow.
Apply DDD during the Backlog to Production flow.
| Approach | Focus | Best For |
|---|---|---|
| Domain Driven Design | Business domain model at center | Complex domains, long-lived systems |
| CRUD/Active Record | Database tables drive design | Simple apps, admin panels |
| Microservices | Deployment & scaling independence | Large teams, scaling needs |
| Clean Architecture | Dependency direction & layers | Testability, framework independence |
DDD provides the strategic boundaries (bounded contexts) that often map to microservices. Clean Architecture works great inside a bounded context. Use DDD to decide what to build; use other patterns for how to build it.
Gather domain experts and developers. Map out domain events on a timeline. This reveals bounded contexts, aggregates, and the ubiquitous language naturally.
Document every important term. Define it precisely. Update it when understanding evolves. Make it accessible to everyone.
Ask: "What makes us unique? What do competitors struggle to copy?" That's your core domain. Apply DDD rigorously there. Be pragmatic elsewhere.
Identify where models diverge. Where does "Customer" mean different things? Draw explicit boundaries. Define how contexts communicate.
Deepen your understanding with these complementary frameworks