Bounded context
A bounded context defines the linguistic boundary where a domain model and its ubiquitous language stay consistent. While a bounded context often aligns with physical boundaries, such as a microservice or a specific module's source code, its main purpose is to give every term a single, unambiguous meaning.
In large systems, identical terms often mean different things in different areas. Defining these boundaries prevents the "big ball of mud" anti-pattern, where a single model becomes too bloated to maintain. Isolating models ensures that logic, validation rules, and schemas remain clean and valid within their specific scope.
Solving linguistic ambiguity
As systems scale, the meaning of terms often diverges depending on the domain. In domain-driven design (DDD), failing to account for these shifts creates polysemes (words with multiple meanings). These are a primary source of logic bugs and developer confusion.
Consider the term "order." Its definition changes based on the perspective of the context:
graph TD
subgraph Sales Context
A[Order] --> B[Contractual Agreement]
A --> C[Commission Calculation]
end
subgraph Fulfillment Context
D[Order] --> E[Physical Pick List]
D --> F[Package Dimensions]
end
subgraph Billing Context
G[Order] --> H[Taxable Event]
G --> I[Accounts Receivable Entry]
end
Trying to force a single, enterprise-wide definition of an order creates a model that is either too generic or incorrectly coupled. A warehouse engineer requires the weight and dimensions found in the fulfillment context; they should not be forced to navigate the legal signatures or commission structures relevant only to sales.
Mirroring boundaries in information architecture
Documentation should reflect the bounded contexts of the system. To maintain clarity, align your information architecture (IA) with the following established domain boundaries:
- Namespace-driven documentation: Organize content by domain, such as
/docs/billing/order or /docs/fulfillment/order. This creates a direct mapping between the documentation and the specific domain services. - Context-specific glossaries: Avoid a global, enterprise-wide glossary. Instead, maintain localized glossaries that define the ubiquitous language of that specific domain to prevent cross-context confusion.
- Isolated schemas: Make sure API documentation reflects context-specific data structures. An identity context user object focuses on authentication (multi-factor authentication) and credentials, whereas a support context user object focuses on ticket history and service-level agreement (SLA) tiers.
The canonical data model trap
Resist the urge to document a universal object model, which is a single schema used by all departments. Universal models result in fat schemas filled with nullable fields that weaken type safety. Instead, document the specialized model required for the specific context to minimize implementation errors.
Navigating dependencies with context maps
A context map tracks how different bounded contexts integrate. Documentation must bridge these gaps to help developers navigate workflows that cross semantic boundaries.
- Upstream and downstream flow: Define the relationship between contexts. If billing (downstream) consumes events from sales (upstream), the documentation should reside where the dependency is managed, typically describing how the downstream context interprets the upstream data.
- Translation strategies:
- Anti-corruption layers (ACL): When a system consumes data from a legacy or external context, document the ACL logic. This translation layer ensures that external definitions do not pollute or leak into the internal domain model.
- Shared kernels: If two contexts share a common subset, such as a shared library or database schema, document this as a shared kernel. This requires explicit documentation of the coordination required between teams, as a change by one team affects the other.
Impact on system maintenance
Explicitly documenting bounded contexts ensures model integrity. This allows developers to work within a specific service without causing unintended side effects in unrelated domains. This isolation reduces cognitive load because engineers only need to master the terminology and logic relevant to their immediate context.
Furthermore, it enables decoupled maintenance; for instance, the tax logic in the billing context can be updated without requiring a logic or documentation audit for the fulfillment or sales contexts.