Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Bounded Context

Pattern

A reusable solution you can apply to your work.

A bounded context draws a line around a part of the system where every term has exactly one meaning, keeping models focused and language honest.

“Explicitly define the context within which a model applies. Keep the model strictly consistent within these bounds, but don’t be distracted or confused by issues outside.” — Eric Evans, Domain-Driven Design

Understand This First

  • Domain Model – each bounded context contains its own domain model.
  • Ubiquitous Language – each context has its own ubiquitous language; terms mean one thing within the boundary.
  • Naming – bounded contexts resolve naming collisions by giving each context authority over its own terms.

Context

You’ve built a domain model and established a ubiquitous language for your project. The model works well when the team is small and the domain is contained. But systems grow. New features arrive. Other teams start contributing. And you discover that the same word means different things in different parts of the organization.

This pattern operates at the architectural level. It addresses the structural problem that emerges when a single model tries to represent everything a business does. Eric Evans introduced bounded contexts in his 2003 book on domain-driven design as the mechanism for managing this complexity: rather than forcing one model to cover every corner of a business, you draw explicit boundaries around regions where a particular model and its language apply.

Problem

How do you keep a domain model coherent when different parts of the system need different definitions of the same concept?

A company’s billing department calls an “account” a record of charges and payments. The identity team calls an “account” a set of login credentials and permissions. If you try to build one Account class that satisfies both, it becomes a bloated object with conflicting responsibilities. Every change to billing logic risks breaking authentication logic, because both live inside the same abstraction. The code compiles, but the concepts have been crushed together.

This problem compounds with AI agents. An agent directed to “update the account service” will read whatever code it finds under that name. If Account mixes billing and identity concerns, the agent can’t tell which meaning applies to the task at hand. It generates code that seems plausible but quietly violates the rules of one domain by applying the rules of the other.

Forces

  • A single unified model across a large system is attractive in theory but collapses under the weight of competing definitions.
  • Different parts of a business genuinely use the same words to mean different things. These aren’t mistakes to correct; they reflect real differences in how each group thinks about the domain.
  • Models need to be internally consistent to be useful. A model that hedges on what “account” means helps nobody.
  • Integration between contexts creates coupling. The more contexts that must talk to each other, the more translation work you take on.
  • Agents need clear, unambiguous context to generate correct code. Vocabulary collisions between contexts are invisible to an agent unless you make the boundaries explicit.

Solution

Draw a boundary around each region of the system where a model and its language apply consistently. Inside that boundary, every term has one definition, every rule is coherent, and the code reflects that model faithfully. Outside the boundary, a different model may use the same words with different meanings, and that’s fine.

The billing context owns its definition of “account” as a ledger of charges. The identity context owns its definition of “account” as a credential set. Neither is wrong. They’re different models for different problems. Where the two contexts need to exchange information, you build an explicit translation layer. Billing doesn’t reach into the identity database; it receives the specific data it needs through a defined interface, mapped into its own terms.

The boundaries aren’t just conceptual. They show up in code as separate modules, services, or repositories. They show up in team structure as separate groups responsible for separate contexts. Conway’s Law applies: the way you divide ownership shapes the software’s architecture, and bounded contexts give you a principled basis for that division.

For agentic workflows, bounded contexts solve a practical problem. When you direct an agent to work on the billing service, you point it at the billing context’s code, glossary, and domain rules. The agent doesn’t see the identity context’s competing definitions. It can’t confuse the two because the boundary limits what’s visible. This is the same principle behind context engineering: controlling what the agent sees determines the quality of what it produces.

In multi-agent systems, bounded contexts map naturally to agent specialization. Each agent owns a context, carries its domain vocabulary, and communicates with other agents through defined interfaces. The 2025-2026 evolution from microservices to agentic architectures extends this idea: where microservices encapsulated service boundaries around domain capabilities, agentic services encapsulate role boundaries where the agent’s prompt, knowledge, tools, and memory all reinforce the same job.

How It Plays Out

An e-commerce company has three teams: catalog, ordering, and shipping. All three deal with “products,” but they mean different things. The catalog team’s product is a description with images, categories, and SEO metadata. The ordering team’s product is a line item with a price, quantity, and tax treatment. The shipping team’s product is a physical object with weight, dimensions, and handling requirements.

Early in the project, they tried sharing a single Product class. Every feature request turned into a negotiation: adding a fragile flag for shipping meant touching a class the catalog team also depended on. The ordering team needed a bundled_price field that made no sense for shipping. Changes in one area kept breaking tests in another.

They split into three bounded contexts. Each context defines “product” on its own terms. When an order is placed, the ordering context sends a message to shipping containing only what shipping needs: product ID, weight, dimensions, and destination. Shipping doesn’t know about prices. Ordering doesn’t know about fragility ratings. The translation happens at the boundary.

When the team later directs an agent to add gift wrapping to the shipping context, the agent’s context includes only shipping’s domain model and glossary. It adds a gift_wrap option to the shipment without touching catalog or ordering code, because those contexts are outside its view.

Example Prompt

“You’re working in the shipping bounded context. Read src/shipping/domain.md for the domain model and glossary. Add a ‘signature required’ delivery option. This affects shipment creation and carrier selection but has nothing to do with ordering or catalog. Don’t modify code outside src/shipping/.”

Consequences

Bounded contexts keep domain models honest. Each model stays small enough to be internally consistent, and the team maintaining it can make changes without coordinating across the entire organization. Code within a context is more cohesive because it serves one model, not a compromise between several.

Integration between contexts requires explicit work. You need to define how data crosses boundaries, which means building APIs, message contracts, or translation layers. This is real overhead, and teams sometimes resist it because sharing a database table feels simpler. It is simpler in the short term. It becomes a trap when two teams need that table to evolve in incompatible directions.

There’s also a judgment call about granularity. Too few contexts and you’re back to a monolithic model with vocabulary collisions. Too many and you spend all your time on integration plumbing instead of building features. Evans recommended starting coarse and splitting when you feel the pain of competing definitions, rather than pre-splitting based on guesses about future complexity.

For agentic systems, bounded contexts provide natural scoping for agent work. An agent working within one context has a smaller, more consistent codebase to reason about, which reduces hallucination and naming confusion. The tradeoff is that cross-context work becomes harder to delegate to a single agent. Tasks that span multiple contexts may need orchestration across specialized agents, each working within its own boundary.

  • Uses / Depends on: Domain Model – each bounded context contains its own domain model.
  • Uses / Depends on: Ubiquitous Language – each context has its own ubiquitous language; terms mean one thing within the boundary.
  • Uses / Depends on: Naming – bounded contexts resolve naming collisions by giving each context authority over its own terms.
  • Enables: Boundary – bounded contexts provide a domain-driven rationale for drawing system boundaries.
  • Enables: Module – contexts often map to module or service boundaries in the code.
  • Enables: Cohesion – code within a bounded context is naturally cohesive because it serves one model.
  • Enables: Interface – the translation layer between contexts is a defined interface.
  • Enables: Contract – inter-context communication relies on explicit contracts.
  • Enables: Context Engineering – bounded contexts define natural scoping boundaries for agent work.
  • Contrasts with: Monolith – a monolith typically has one shared model; bounded contexts partition it.

Sources

  • Eric Evans introduced bounded contexts in Domain-Driven Design: Tackling Complexity in the Heart of Software (2003) as part of his strategic design vocabulary. The core ideas in this article – drawing explicit model boundaries, allowing different contexts to define the same term differently, and building translation layers at the edges – originate in that book.
  • Martin Fowler’s BoundedContext bliki entry distilled the concept into a concise explanation and popularized the idea that bounded contexts are the single most important pattern in DDD for large systems.
  • Matthew Skelton and Manuel Pais connected bounded contexts to team cognitive load in Team Topologies (2019), arguing that context boundaries should align with team boundaries so that no team has to hold more than one model in its head.

Further Reading

  • Vaughn Vernon, Implementing Domain-Driven Design (2013) – the most thorough practical guide to implementing bounded contexts, including context mapping strategies for how contexts relate to each other.
  • Eric Evans, Domain-Driven Design Reference (2015) – a free summary of DDD concepts, including bounded contexts, available as a PDF. Good for quick reference after reading the full book.