open atlas
↑ Back to track
Architecture Patterns ARCH · 06 · 01

Bounded contexts

A bounded context is the explicit boundary within which a domain model is consistent. The same word — Order, Customer, Product — means a different model in each context. Bounded contexts are the primary unit of decomposition in DDD.

ARCH Senior ◷ 24 min
Level
FoundationsJuniorMiddleSenior

The B2B order platform had a single “Order” entity shared across the entire backend. It had 47 fields. The Sales team needed an Order to capture negotiated line items, discount tiers, and the assigned account executive. The Billing team needed an Order to track invoice amounts, payment terms, and tax jurisdiction. The Shipping team needed an Order to know the delivery address, package dimensions, and carrier preferences. Each team kept adding fields to the same entity. The entity grew. The fields for Sales meant nothing to Billing. The fields for Billing confused the Shipping service. Validation rules clashed: Sales said an Order was valid the moment a quote was signed; Billing said it was only valid once a payment method was confirmed; Shipping said it was only valid once a warehouse had picked the items. Three teams, three definitions of “valid Order,” all fighting over one class. A senior architect joining the team asked a single question: “Do you really believe Sales, Billing, and Shipping are talking about the same thing when they say ‘Order’?” They were not. The entity had three distinct identities conflated into one. The fix was not to add more validation flags. It was to draw three explicit boundaries and give each team its own model.

The central problem: one word, many models

Domain-driven design starts from an observation that trips up almost every large system: natural language is ambiguous. The word “Customer” in a CRM means a contact with a sales history, a relationship owner, and a lead score. In a billing system, “Customer” means an account with a payment method, a credit limit, and outstanding invoices. In a shipping system, “Customer” means a delivery address and a contact phone number.

If your codebase has a single Customer class shared by all three systems, one of two things happens. Either the class grows to contain all three meanings (a 60-field god object that no team fully understands), or the class carries the meaning of whichever team wrote it first, and every other team constantly adapts around fields that do not apply to them.

Eric Evans’s insight in Domain-Driven Design (2003) was that trying to unify these into one model is not a goal — it is a mistake. Each subdomain has its own language, and that language produces its own model. The goal is not a single unified model; it is a set of models that are internally consistent within their boundaries.

A bounded context is that boundary. It is the explicit declaration: “Within this context, the word ‘Customer’ means exactly this, the word ‘Order’ means exactly this, and this model is internally consistent.” Outside this context, the same word may mean something else — and that is fine, because we have made the boundary explicit.

Subdomains vs bounded contexts: problem space vs solution space

These two terms are often used interchangeably and they should not be. The distinction is between what the business does and how your code organizes it.

A subdomain is a part of the business problem space — it is discovered by talking to domain experts, not designed by engineers. Your business has a Sales subdomain, a Billing subdomain, a Shipping subdomain. These exist regardless of how you build software. Some subdomains are core (they differentiate the business — getting them right is a competitive advantage), some are supporting (necessary but not differentiating — you could buy them), and some are generic (solved problems — just use off-the-shelf software).

A bounded context is a decision in the solution space — it is designed by your team. One subdomain may be served by one bounded context (the common case) or by multiple bounded contexts (when a large core domain warrants separate teams or separate models for different aspects). One bounded context may span multiple subdomains (sometimes done with generic/supporting subdomains that are simple enough not to warrant their own context).

The heuristic: identify subdomains first (by talking to the business), then decide how many bounded contexts to create for each subdomain based on team topology, model complexity, and deployment needs.

Why this works

Why does the distinction matter in practice? Because teams often conflate the two and end up with a bounded context boundary that does not match any real business boundary. A context split driven by technology (“we’ll have a microservice for authentication”) without a corresponding model split just creates an RPC call where a function call used to be — the same logical model, now distributed. The bounded context boundary is meaningful only when the model on each side is genuinely different. If your “two contexts” are running the same conceptual model, you have distributed a monolith, not decomposed a domain.

What a bounded context actually contains

A bounded context is not just a service boundary or a database boundary (though it often aligns with those). It is a linguistic and model boundary that contains:

  • A ubiquitous language — the precise vocabulary shared by developers and domain experts in this context. “Order” in the Sales context has a specific definition that every developer and every product manager on that team uses consistently. (The next lesson focuses on ubiquitous language in depth.)
  • A domain model — the classes, aggregates, value objects, and rules that implement that vocabulary. The model is valid and consistent within the boundary. Nothing outside the boundary should directly access the internals of this model.
  • An explicit integration interface — the boundary is explicit. Other contexts integrate through events, APIs, or translation layers — not by importing each other’s internal classes.

The boundary is enforced in code. In a monolith, this means package boundaries enforced by architecture tests (ArchUnit, dependency-cruiser, or module system constraints). In a service architecture, the service boundary IS the context boundary — you cannot import across a network call.

The primary unit of decomposition

In strategic DDD, bounded contexts are the primary unit of decomposition. Before asking “how many microservices should we have?” or “what should each service do?”, you ask: “how many bounded contexts does this domain have, and what is the model in each?”

Each bounded context maps to:

  • One team (or one squad) with clear ownership
  • One ubiquitous language shared between developers and domain experts on that team
  • One codebase (or at least one module with enforced boundaries)
  • One deployment unit (in a services architecture) or one package cluster (in a monolith)

The size of a bounded context is driven by how much model can remain internally consistent under one team’s ownership — not by lines of code, not by database tables, not by API endpoints.

Quiz

The B2B platform has a single shared `Order` class used by Sales, Billing, and Shipping. The class has grown to 47 fields. A developer proposes: 'We should split this into three subclasses — SalesOrder, BillingOrder, ShippingOrder — all extending a base Order class.' Why does this not solve the bounded-context problem?

Quiz

Your team has identified three subdomains: Order Management (core), Tax Calculation (supporting), and Email Notifications (generic). A junior developer proposes one bounded context per subdomain. A senior architect says: 'We should use off-the-shelf software for Tax and Email — that means they are not our bounded contexts at all.' What is the architect's reasoning?

Quiz

Two engineers are debating the bounded context split for a new feature. Engineer A says: 'Customer means the same thing in Sales and in Customer Support — they both care about the same person.' Engineer B says: 'But Sales cares about the customer's purchase history, lead score, and account executive; Support cares about their open tickets, service tier, and escalation history — those are genuinely different models.' How do you determine whether to use one bounded context or two?

Recall before you leave
  1. 01
    What is a bounded context, and why does the same word intentionally mean different things in different contexts?
  2. 02
    What is the difference between a subdomain and a bounded context?
  3. 03
    What does 'primary unit of decomposition' mean in the context of DDD?
Recap

The opening story’s 47-field Order entity was not a problem of poor object-oriented design. It was a problem of three distinct models — Sales, Billing, Shipping — being forced into one class because no one had drawn an explicit boundary.

A bounded context solves this by declaring: within this boundary, this word means exactly this, this model is consistent, and changes here do not require coordination with that other team. The boundary is linguistic (ubiquitous language), model-level (a consistent set of classes and rules), and structural (enforced by package or service boundaries in code).

Bounded contexts are not the same as subdomains. Subdomains are the business’s problem space — discovered, not designed. Bounded contexts are your solution space — designed by your team based on subdomains, team topology, and model complexity.

The next lesson examines the ubiquitous language inside a bounded context — why it is a design tool, not just a naming convention, and how naming drift is the first signal that a boundary is in the wrong place.

Practice

Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.

recallapplystretch0 of 4 done

Something unclear?

Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.

Apply this

Put this lesson to work on a real build.

shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.