Organization and Bounded Context sit at the top of the domain metamodel. An organization is the outer boundary and wrapper of the work — the scope of what is being modeled, whether that is a product, a business unit, or a company. It holds one or more bounded contexts. A bounded context defines one or several domain models whose languages are mutually consistent and expresses the relations between those models. The patterns at each context’s outer boundary — who owns the contract, who translates, who absorbs change — are the true design decisions. This page covers both.
Organization
An Organization is the top boundary and wrapper of the work. It names the scope of what is being modeled — the product, the business unit, the company, or any envelope that bounds the engagement — and makes that scope explicit before anything else is said about the domain. It carries no behavior of its own; structurally it is a named container that holds one or more bounded contexts and anchors cross-cutting concerns, most importantly requirement provenance: when system requirements come from a file, the requirements-source attribute is declared on the organization (or on any of its bounded contexts) so that every satisfies identifier downstream has a resolvable origin.
Think of the organization as the answer to “for whom, and within what frame, is this model being written?” Everything inside it — contexts, modules, entities, operations, properties — exists inside that frame and inherits its provenance.
Example:
organization Acme {
requirements-source "specs/acme-requirements.sysreq"
context OrderContext { ... }
context PaymentContext { ... }
context ShippingContext { ... }
}
Bounded Context
A Bounded Context defines one or several domain models and the relations between them. Inside the context, the language is mutually consistent: a word such as order or rider has one agreed meaning across every model the context contains. A bounded context carries a shortname used throughout the model (and in generated code), it holds zero or more modules that decompose its interior, and it belongs to exactly one organization.
Allowing several domain models inside a single context is deliberate. A context that handles complex behavior often needs more than one coherent perspective on the same domain — a write-side model anchored in commands and invariants, a read-side model shaped by the queries it serves, a projection model used for integration, a lifecycle model captured as a state machine. Each of these is a domain model in its own right. They share the ubiquitous language of the context, but they are organized differently because they answer different questions. The relations between them — which model is derived from which, which events link one to another, which invariants must hold across the set — are part of what the bounded context declares.
The ubiquitous language
The ubiquitous language is the shared vocabulary of a bounded context. Inside the context, every concept — entity, value, command, event, invariant, operation — is named with a term that domain experts, product managers, and engineers all use the same way. The language is ubiquitous because it appears everywhere the system is discussed: in conversations with stakeholders, in PRD features and user stories, in EARS requirements, in the domain model itself, and in the code that realizes it. There is no separate “technical” name and “business” name for the same thing — drift between the two is exactly the friction the discipline is designed to remove.
Inside one bounded context, the language is internally consistent: a word like order or rider has one agreed meaning. At a context boundary the language often shifts — “order” in the order context is not necessarily “order” in the fulfillment context — and that shift is made explicit through a context-map pattern, typically an Anti-Corruption Layer that translates the upstream model into the local language before it enters the domain.
The language is defined in the domain model and adopted by the layers above. The domain model is the canonical form; the PRD and the system requirements should align with it rather than coin parallel vocabularies. This alignment is what makes the traceability chain readable without a translation key.
The system(s) inside a bounded context
A bounded context typically has one or several systems — implemented in software — that make its domain models live. A system is the running incarnation of the context: it accepts commands, executes operations, holds state, emits events, and exposes the context’s interfaces to the rest of the world. Where the domain model says what must be true, the system is the thing for which it must be true.
This is the pivot point between the system requirements layer and the domain model layer. Every EARS requirement begins with “the system shall…” — that “system” is the software system(s) living inside a bounded context. A requirement is scoped to a bounded context (see Requirement relations) precisely because the system it talks about is one of that context’s systems. The traceability chain therefore runs:
Requirement ──scoped-to──▶ Bounded Context
│
├── contains System(s) ← the running software
│
└── defines Domain Model(s) ← the shape the system must take
Domain elements (entity, operation, invariant, …) carry satisfies [REQ-…] on them, closing the loop: the domain model of a context is exactly the shape its system must take to satisfy the requirements scoped to that context. A single bounded context may host multiple systems when the domain naturally separates along deployment or ownership lines (a public-facing API, a background worker, a batch job) — each of them realizing some subset of the context’s domain models, while all of them sharing its ubiquitous language.
Three rules are non-negotiable:
- Do not use a bounded context for decomposition. Splitting a single consistent language into two contexts because “the code is getting big” is a mistake. When in doubt, use a module — modules decompose a context without breaking the language.
- Interactions between bounded contexts should be asynchronous. Synchronous cross-context calls couple release cycles, hide failure modes, and defeat the purpose of having a boundary. Interactions within a context — between domain models or between modules — can be synchronous because the language is shared.
- Transactions cannot span bounded contexts. There is a rupture of transactional consistency at every context boundary. Cross-context invariants must be expressed as agreements maintained by reconciliation, not as ACID transactions.
Example:
context OrderContext {
shortname "ord"
satisfies [REQ-ORG-001]
module placement { ... }
module fulfillment { ... }
}
Context Map Patterns
A context map pattern defines the behavioral constraints that govern how two bounded contexts interact. The pattern says who controls the shared model, how translation happens, and what coupling is accepted. Patterns are grouped by the position of the context in the relationship:
- Upstream — the context that provides: Open Host Service.
- Downstream — the context that consumes: Customer/Supplier, Conformist, Anti-Corruption Layer.
- Symmetric — shared responsibility: Shared Kernel, Published Language, Partnership, Separate Ways.
Picking a pattern is a design commitment. It dictates who negotiates, who translates, and who absorbs upstream breakage. The rest of this page enumerates the eight patterns, each with its constraints and typical use.
Open Host Service (upstream)
The upstream context exposes a well-defined, stable protocol for all its consumers. The protocol is designed for general use, not tailored to any single downstream.
Constraints:
- Publish a versioned interface (API, message schema, or event contract) that serves as the single integration point for all consumers.
- Do not break existing consumers without a versioning and deprecation strategy.
- Do not accommodate any single downstream’s model — the interface reflects the upstream model only.
- Downstreams are responsible for translating the protocol into their own model.
Typical use: a bounded context that serves multiple consumers and needs a stable, public-facing contract.
Customer / Supplier (downstream)
The downstream (customer) has influence over the upstream (supplier). The supplier accommodates reasonable requests about the shared interface.
Constraints:
- The supplier accepts feature requests and prioritization input from the customer.
- Interface changes are negotiated before deployment.
- The customer communicates needs explicitly — formats, required data, timing.
- Both sides agree on acceptance criteria, ideally as contract tests both run independently.
- The customer may still need a translation layer, but has leverage to reduce translation burden.
Typical use: two teams in the same organization where the downstream team’s delivery depends on the upstream team’s output and has enough standing to negotiate.
Conformist (downstream)
The downstream adopts the upstream model as-is. No translation.
Constraints:
- The downstream uses the upstream model’s types, naming, and structure directly in its own domain layer.
- Upstream changes propagate directly — no buffering, no adaptation.
- The downstream does not request changes (no negotiating power, or chooses not to use it).
- Full coupling to upstream evolution is accepted — a breaking change upstream is a breaking change downstream.
Typical use: integrating with a dominant external system (a regulatory body’s data model, a platform API) where the cost of translation outweighs the cost of coupling, or where the upstream is unwilling to negotiate.
Anti-Corruption Layer (downstream)
The downstream builds an explicit translation layer that isolates its own model from the upstream. The upstream model never leaks into the downstream domain.
Constraints:
- Implement a translation component (the ACL) that converts upstream messages, types, and concepts into the downstream ubiquitous language before they enter the domain layer.
- The downstream domain layer never references upstream types directly.
- The ACL is the sole point of contact between the two contexts — no domain object, domain service, or application service bypasses it.
- When the upstream changes, only the ACL needs modification; the downstream domain stays stable.
- The ACL is an infrastructure service in the downstream’s hexagonal architecture.
Typical use: integrating with a legacy system, an external API with a conflicting model, or any upstream where model leakage would corrupt the downstream ubiquitous language.
Shared Kernel (symmetric)
Both contexts share a common subset of the model — types, events, interfaces — that they co-own and co-evolve.
Constraints:
- Both sides agree on the exact boundary of the shared kernel: what is shared, what remains private.
- Neither side modifies the kernel unilaterally — all changes require joint agreement.
- Both run shared tests (contract or integration) against the kernel after every change.
- Keep the kernel as small as possible. Anything that can be owned by a single context should not be in the kernel.
- Tight coupling of release cycles is accepted; coordinated deployments are required when the kernel changes.
Typical use: two closely collaborating teams working on overlapping domain concepts where translation cost would exceed coordination cost.
Published Language (symmetric)
Both contexts communicate through a well-documented, shared language (schema, standard, protocol) that is not owned by either context.
Constraints:
- Both contexts translate their internal models to and from the published language at their boundaries — neither uses it as its internal model.
- The language is documented independently of both contexts (schema, specification, or industry standard).
- Changes follow a governed process (versioning, review) that neither context controls unilaterally.
- Inbound messages are validated against the schema before translation.
Typical use: integration via industry standards (HL7, FIX, EDI), shared event schemas in an event-driven architecture, or any situation where a neutral interchange format reduces bilateral coupling.
Partnership (symmetric)
Both contexts are developed by teams that coordinate closely and succeed or fail together. Neither dominates.
Constraints:
- Both teams plan and prioritize integration work jointly — neither can unilaterally deprioritize the shared interface.
- Both contexts adapt their interfaces through mutual negotiation when needs change.
- Integration failures are shared problems — no “other side” blame.
- Both teams maintain joint integration tests.
- Synchronized development cadence is implied; if one team accelerates or slows, the integration surface is at risk.
Typical use: two teams building complementary parts of a core business flow where the boundary is somewhat arbitrary and could shift.
Separate Ways (symmetric)
Both contexts decide not to integrate. Each solves its own problems independently, even if that means duplicating concepts.
Constraints:
- Neither context depends on the other’s model, messages, events, or interfaces in any way.
- If both need similar functionality, each implements its own version.
- No translation layer, shared kernel, or published language exists between the two.
- The decision is explicit and documented, including the rationale (integration cost > benefit, domains are independent, team autonomy prioritized).
- The decision is revisited periodically — separate ways is often a temporary choice that becomes permanent by inertia.
Typical use: contexts operating in genuinely distinct domains with no meaningful overlap, or where the organizational cost of coordination exceeds the technical cost of duplication.