Bounded Context
A bounded context is a logical boundary within a system inside which one ubiquitous language applies. It encapsulates a set of services that share a deployment cycle or a domain model.
Ubiquitous language is realised as specific canonical models, each representing the same domain object as it is understood in one context. Different canonical models are needed because a single unified domain model for a large system is rarely feasible or cost-effective — “customer” means something different to billing than it does to delivery, and forcing one definition on both produces a model neither side recognises. Unambiguous language inside each boundary is what keeps developers, the business and users talking about the same thing.
Examples
Section titled “Examples”In an e-commerce system:
- Order context
- Delivery context
- Invoice context
How to decide where the boundary falls
Section titled “How to decide where the boundary falls”With one large context everything becomes equally critical. There is no way to make one part of the system redundant without making all of it redundant, and a change to one piece of functionality can reach anything.
Bounded contexts structure complex logic into services small enough to be understood, which makes it possible to:
- Contain complexity within a boundary
- Define and implement transactional boundaries
- Allocate critical features to a context that can be treated as critical, leaving the rest alone
- Keep a small number of teams understanding and owning each context
In a traditional DDD application the domain model is a shared resource consumed by every application service, repository and domain service in the context. If the application-services layer is implemented as microservices, each service has to be independently deployable — and that is what Aggregates provide, by making the transactional unit explicit and small enough to sit inside one service.
Event-driven systems and bounded contexts
Section titled “Event-driven systems and bounded contexts”Implementing an event-driven system alongside a domain-driven architecture introduces the idea of a domain event: something the business recognises as having happened, named in the language of the context that owns it.
Order accepted is a domain event of the order context. The invoice and delivery contexts are interested in it because it starts processes of their own. The event is the whole of the coupling between them: neither downstream context calls into the order context, and neither needs the order context’s internal model — only the event and the language it is stated in.
That is also where the translation work lives. An event leaving one context carries the vocabulary of the context that emitted it, and the consuming context has to map it onto its own canonical model rather than adopt the producer’s. Skipping that mapping is how one context’s model quietly leaks into every other.