8 Domain-Driven Design Concepts
Eight domain-driven design concepts covering models, boundaries, language, and aggregates.
Domain-Driven Design, or DDD, is most useful when the hard part of the software is the business itself. If the problem is mostly CRUD screens or infrastructure plumbing, the vocabulary can feel heavy. When the domain contains policy, exceptions, timing rules, and teams that use the same words differently, DDD helps turn ambiguity into explicit design.
1. Ubiquitous language
Ubiquitous language means engineers, product people, and domain experts use the same important terms in conversations, documentation, and code. If the business says settlement, but the code calls it payout in one service and transfer in another, misunderstanding is already baked in. Shared language reduces translation errors before they become technical debt.
2. Bounded context
A bounded context is the space within which a model has one precise meaning. Customer in billing may not mean the same thing as customer in support or identity. DDD does not force a single universal model. It encourages teams to draw boundaries so each model stays coherent and can evolve without endless semantic arguments.
3. Entity
An entity is defined by identity over time rather than by its current attributes. An order remains the same order after its status changes, line items are edited, or shipping information is updated. Identity matters because behaviour and history attach to that thing across multiple transitions.
4. Value object
A value object is defined entirely by its attributes. Money, date range, percentage, and postal address are common examples. Value objects are often immutable because replacing a value is simpler and safer than mutating it in place. They also make illegal states harder to represent when constructors enforce rules up front.
5. Aggregate
An aggregate is a cluster of domain objects treated as one consistency boundary. The aggregate root controls access and protects invariants that must change together. This keeps transactional work focused. Instead of locking half the domain model for every update, the design decides which rules truly need atomic enforcement.
6. Domain service
Some business behaviour does not fit naturally on one entity or value object. A domain service holds that logic without forcing it into the wrong place. The key test is whether the service expresses business policy rather than technical utility. If it mostly coordinates repositories and HTTP calls, it is probably an application service instead.
7. Repository
A repository abstracts persistence for aggregates using domain language. It should feel like a collection of meaningful business objects, not a generic helper for arbitrary SQL. Good repositories keep storage concerns from leaking across the model while still making load and save behaviour explicit enough to reason about.
8. Domain event
A domain event records that something meaningful happened in the business, such as InvoiceIssued or PaymentCaptured. Events help other parts of the system react without tight coupling to the original command path. They also make business timelines easier to understand because the event names speak in domain terms.
The practical point of DDD
DDD is not about collecting clever nouns. It is about choosing boundaries that match real business meaning, keeping the language stable, and protecting important invariants where they belong. Used well, it helps teams change software without rediscovering what the business meant every sprint.
The model is successful when code, conversations, and behaviour line up. If the vocabulary becomes ceremony with no clearer decisions, the design has missed the reason DDD exists.