---
title: "Domain-Driven Design"
type: "architectural-pattern"
slug: "domain-driven-design"
url: "http://localhost:3000/en/architectural-patterns/domain-driven-design.md"
also_known_as: "DDD"
description: "An approach to software development that centers the design on a rich model of the business domain, expressed in a language shared by engineers and domain experts."
languages: ["typescript"]
---
# Domain-Driven Design

_Also known as: DDD_

> An approach to software development that centers the design on a rich model of the business domain, expressed in a language shared by engineers and domain experts.

## Intent

Tackle complexity in the heart of software by modeling the business domain explicitly, and by keeping that model — and the code that expresses it — in tight alignment with the language used by the people who understand the domain.

## Problem

As a system grows, business rules tend to scatter across controllers, services and database queries. The code drifts away from how the business actually talks about its work, so every conversation needs translation and every change risks breaking a rule nobody remembered.

Data-centric designs make this worse: models become anemic bags of getters and setters, invariants live nowhere in particular, and the system slowly turns into a "big ball of mud" that only a few people dare to touch.

## Solution

Domain-Driven Design attacks the problem on two levels.

**Strategic design** divides a large domain into _bounded contexts_ — explicit boundaries within which a model and its language are consistent — and maps the relationships between them. Each context is free to model the same concept differently where the business genuinely sees it differently.

**Tactical design** builds a rich model inside a context from a small set of building blocks, and insists on a _ubiquitous language_: the same terms appear in conversations, in the model and in the code.

## Structure

The tactical building blocks:

* **Entities** — objects defined by identity that persists over time (a `Customer`, an `Order`).
* **Value objects** — immutable objects defined by their attributes (a `Money`, an `Address`).
* **Aggregates** — clusters of entities and value objects with a single _aggregate root_ that guards the cluster’s invariants and is the only entry point for changes.
* **Repositories** — collection-like interfaces that load and persist whole aggregates, hiding storage details.
* **Domain services** — stateless operations that don’t naturally belong to a single entity.
* **Domain events** — records of something meaningful that happened in the domain.

The strategic blocks — **bounded context** and **context map** — organize these models across teams and subsystems.

## Applicability

* Use it when the **core complexity is in the business rules**, not the technology — logistics, finance, insurance, scheduling.
* Use it when several teams must agree on a shared, evolving understanding of a domain.
* **Avoid it** for simple CRUD or data-entry applications, where the modeling overhead buys you little.

## How to Implement

1. Talk to domain experts and **distill the ubiquitous language**; write down the terms and what they mean.
2. Identify the **core domain** — the part that gives competitive advantage — and focus modeling effort there.
3. Carve the domain into **bounded contexts** and draw a context map of their relationships.
4. Within a context, model **aggregates** so that each one enforces its own invariants in one transaction.
5. Load and save aggregates through **repositories**; publish **domain events** for things other contexts care about.
6. Refine continuously — the model is never “done,” it evolves as understanding deepens.

## Pros

* Keeps code aligned with the business, so changes map cleanly to requirements.
* Isolates complexity behind bounded contexts.
* A shared language reduces miscommunication between engineers and experts.
* Rich domain logic is decoupled from infrastructure and easy to unit-test.

## Cons

* Steep learning curve and a real investment in domain modeling.
* Overkill for simple or mostly-CRUD applications.
* Requires ongoing access to domain experts.
* Misapplied, the building blocks become ceremony without benefit.
## Relations

**Related patterns**

- [CQRS](/en/architectural-patterns/cqrs.md)

## Code Examples

### typescript

```typescript
class Money {
  constructor(readonly amount: number, readonly currency: string) {
    if (amount < 0) throw new Error('amount must be non-negative')
  }
}

// Aggregate root: the only place Order invariants are enforced.
class Order {
  private lines: { sku: string; qty: number }[] = []
  constructor(readonly id: string) {}

  addLine(sku: string, qty: number) {
    if (qty <= 0) throw new Error('quantity must be positive')
    this.lines.push({ sku, qty })
  }
}
```

