Bounded Context
Define the boundary within which a domain model is defined and applicable
Tags
Overview
Purpose
Define the boundary within which a domain model is defined and applicable
Context
Large systems or organizations where multiple teams or subsystems model overlapping real-world concepts differently. The system is complex enough that a single unified model would be either too large to comprehend or too politically contested to agree upon. Different subsystems have legitimate reasons for modeling the same concept differently — different use cases, different performance requirements, different regulatory constraints. The system needs to support both independent evolution within contexts and controlled communication between contexts.
Problem
How to prevent model corruption when multiple subsystems use different
representations of overlapping concepts, while still enabling controlled
communication between those subsystems?
Forces:
(1) Different subsystems have legitimately different models for the same real-world concept
(2) A single unified model becomes too complex and contested as the system grows
(3) Teams need autonomy to evolve their models independently
(4) Some concepts must be shared or translated across subsystem boundaries
(5) Without explicit boundaries, models bleed into each other (concept leakage)
(6) Translation between models adds integration complexity and runtime overhead
(7) The ubiquitous language must be precise, but the same term means different things in different areas
Solution
Explicitly define a Bounded Context for each area of the system that has a coherent, internally consistent domain model. Within a Bounded Context, enforce a single Ubiquitous Language — every term has exactly one meaning, agreed upon by developers and domain experts within that context. The same real-world concept may have different model representations in different Bounded Contexts, and this is intentional, not a defect.
At context boundaries, define explicit translation mechanisms. Use a Context Map to document the relationships between all Bounded Contexts in the system. For each inter-context relationship, choose an integration pattern: Anti-Corruption Layer (translate foreign models to prevent contamination), Shared Kernel (small shared model owned jointly), Open Host Service (published API with a Published Language), or Conformist (downstream adopts upstream model).
The boundary is a first-class architectural element — not just a naming convention but an enforced constraint in code, database schemas, and deployment units.
Consequences
Benefits: - Model integrity: each context maintains a coherent, non-contradictory model - Team autonomy: teams can evolve their models without cross-team coordination - Linguistic precision: the ubiquitous language is unambiguous within each context - Independent deployment: contexts can be deployed, scaled, and versioned independently - Reduced complexity: each context's model is small enough to understand fully - Explicit integration: inter-context communication is documented and controlled
Liabilities: - Duplication: the same real-world concept may be modeled multiple times in different contexts - Translation overhead: every cross-context interaction requires mapping between models - Boundary decisions: choosing where to draw context boundaries is a difficult strategic decision - Context mapping maintenance: the Context Map must be kept current as the system evolves - Refactoring difficulty: moving a concept from one context to another is a major migration - Discovery cost: newcomers must learn which context owns which concepts
Collaborations
Each BoundedContext maintains its own UbiquitousLanguage and domain model independently. When Context A needs to communicate with Context B, the interaction is mediated by one of the strategic integration patterns. If Context A is downstream and wants to protect its model, it establishes an AntiCorruptionLayer that translates Context B's model into Context A's terms. If two contexts share a small common model, they establish a SharedKernel with joint ownership and coordinated changes. The ContextMap documents all these relationships at the system level, making the integration topology visible to all teams. Context boundaries are enforced in code (separate modules/services), data (separate database schemas), and deployment (separate deployable units).
Structure
Participants:
- BoundedContext: an explicit model boundary with owned language and invariants
- UbiquitousLanguage: the vocabulary enforced within a context
- ContextMap: system-wide documentation of all contexts and relationships
- AntiCorruptionLayer: translator preventing model contamination
- SharedKernel: jointly-owned model subset
Relationships:
- BoundedContext contains UbiquitousLanguage (ownership)
- BoundedContext contains domain objects, aggregates, services (ownership)
- ContextMap documents all BoundedContexts and their relationships (documentation)
- AntiCorruptionLayer sits between two BoundedContexts (mediation)
- SharedKernel is co-owned by two or more BoundedContexts (joint ownership)
SBX Workspace as Context Map:
Context: SBX Core — entities, protocols, governance, FDD layers
Context: ShredBX — knowledge artifacts, patterns, standards, articles
Context: Bestays — properties, availability, bookings, guests
Shared Kernel: — audit_log schema, user identity, infrastructure
Integration: — Anti-Corruption Layers at service boundaries (API)
Implementation
In SBX Workspace (Project as Bounded Context):
1. Each project has its own database schema: sbx, shredbx, bestays
2. Each project has its own Go packages with independent domain types
3. Shared infrastructure (PostgreSQL, Redis) is not shared domain model
4. Cross-project communication happens through explicit API calls
Context Boundary Enforcement:
1. Separate Go modules per project — import boundaries are compile-time enforced
2. Separate database schemas — no cross-schema foreign keys
3. Separate API surfaces — each project owns its endpoints
4. Shared kernel limited to: audit_log, user identity primitives, infrastructure config
Anti-Corruption Layer Implementation:
1. Define adapter interfaces in the consuming context's domain layer
2. Implement adapters in the consuming context's SI layer
3. Adapters translate foreign types to local types at the boundary
4. Never expose foreign context types beyond the adapter
Context Map Maintenance:
1. Document contexts in workspace.yml (already done: projects, clients)
2. Document relationships in infrastructure service definitions
3. Review context map when adding new cross-project features
4. Each decision that crosses context boundaries must reference the Context Map
Example
Consider a workspace management platform (SBX) that serves multiple client
projects: a software development knowledge base (ShredBX), a property management
system (Bestays), and the workspace tooling itself (SBX core). All three projects
deal with "entities" — but the word means something different in each context.
In SBX core, an entity is a namespace package with FDD layers and protocol
conformance. In ShredBX, an entity is a knowledge artifact with patterns,
standards, and educational content. In Bestays, an entity is a property listing
with availability, pricing, and guest reviews. When developers use the term
"entity" without qualifying which context they mean, requirements are
misinterpreted, code is placed in the wrong module, and database schemas
accumulate columns that belong to other contexts. A property listing gains
a `conforms_to` field (SBX concept), while a protocol definition gains a
`price_per_night` field (Bestays concept). The unified model becomes a
contradictory mess that serves no context well.
Resolution
Applying Bounded Context to the SBX workspace: each project becomes an explicit Bounded Context with its own model, language, and database schema. "Entity" in SBX core means a namespace package with FDD layers. "Entity" in ShredBX means a knowledge artifact. These are not the same concept forced into one model — they are different models for different purposes, explicitly bounded. When ShredBX needs to reference SBX entity metadata (e.g., for the /modeling page), it does so through SBX's API, translating via an Anti-Corruption Layer in ShredBX's SI layer. The workspace.yml serves as the Context Map, documenting which projects exist, how they relate, and which infrastructure they share. The `price_per_night` field never appears in SBX core. The `conforms_to` field never appears in Bestays. Each context's model remains coherent and comprehensible.
Known Uses
- Microservice architecture — each service is a Bounded Context with its own database, API, and domain model (Netflix, Amazon, Spotify)
- SBX workspace — each project (sbx, shredbx, bestays) is a Bounded Context with its own database schema, Go module, and ubiquitous language
- Shopify modular monolith — Bounded Contexts as Rails engines with enforced module boundaries and explicit inter-context APIs
- UK Government Digital Service (GDS) — separate Bounded Contexts for tax, benefits, identity, with Anti-Corruption Layers at service boundaries
See Also
- aggregate: Aggregates are consistency boundaries within a Bounded Context. The context boundary is the outer boundary; aggregate boundaries are inner boundaries.
- anti-corruption-layer: Anti-Corruption Layer is the primary translation mechanism between Bounded Contexts, preventing foreign model contamination
- layers: Each Bounded Context may be internally layered. The layer pattern provides intra-context structure; Bounded Context provides inter-context structure.
- facade: Open Host Service (a Bounded Context integration pattern) uses Facade to present a simplified interface to downstream contexts