skip to content

Bounded Contexts

A bounded context is an explicit boundary inside which a model and its language are consistent, and outside which the same word may mean something else. You will learn to find context seams in the domain and to stop one model from corrupting another.

part ofSoftware design & architectureoverview, primer and where to startread it →
on this pageshow

questions

6

In Domain-Driven Design, what is a bounded context, and why might the word 'Order' mean something different inside a company's Sales system than inside its Shipping system?

level: juniorimportance: must knowfreq 75%

answer

  1. one model, one boundary
  2. same word, different meaning across contexts
  3. ubiquitous language is local not global
  4. duplication is OK across contexts
  5. boundary != necessarily microservice

basics

~10 s

A bounded context is a boundary around a part of a system where a specific model and its terms have one exact meaning. Outside that boundary, the same word can mean something completely different.

solid answer

~50 s

A bounded context is an explicit boundary - typically a module, service, or subsystem owned by one team - inside which a domain model and its vocabulary (the "ubiquitous language") stay internally consistent and unambiguous. Inside Sales, "Order" might mean a priced, discountable line-item bundle; inside Shipping, "Order" might mean a physical package with weight, dimensions, and a delivery address. Neither is "the real" Order - they're different models for different purposes, and DDD accepts that duplication rather than forcing one shared model to satisfy every concern. The boundary matters because a shared word without a shared context breeds silent misunderstanding: a Shipping field added to Order "because Sales asked" is a symptom of a missing boundary. Contexts usually align with team ownership so each team can evolve its own model's language without cross-team negotiation on every change.

go deeper

for a junior

Should state the core idea in one or two sentences: a boundary where a model's terms mean one specific thing, and different contexts can define the same word differently. Doesn't need context-mapping pattern names.

for a middle

Should connect the boundary to team ownership and be able to give a second concrete example beyond the interview's own, e.g. 'Product' in Catalog vs Pricing.

for a senior

Should explain why forcing one shared model across contexts causes coupling and stalls independent delivery, and mention that translation happens explicitly at the boundary rather than by osmosis.

for a principal

Should discuss how bounded context boundaries interact with organizational structure (Conway's Law) and be able to argue when NOT to introduce a new boundary because the translation overhead would exceed the isolation benefit.

## What a bounded context actually is A bounded context is Domain-Driven Design's answer to a problem every non-trivial software system eventually hits: the same business word means different things to different people, and pretending there's one universal definition creates a model nobody can safely change. Concretely, a bounded context is an **explicit boundary** - conceptual, and usually also a boundary in code (a module, service, or deployable unit) and in team ownership - inside which a specific domain model, along with the vocabulary used to describe it (DDD calls this the '**ubiquitous language**'), is internally consistent and has exactly one meaning. Outside that boundary, the same English word is allowed to mean something else entirely, because it belongs to a different model solving a different problem. ## One word, two models Take 'Order' at a retail company. | Context | The Order it owns | |---|---| | **Sales** | Inside a Sales context, an Order is a shopping-cart-derived object: it has line items, prices, discounts, a payment method, and a status like 'placed' or 'cancelled' - everything needed to answer 'what did the customer agree to buy and pay?'. | | **Shipping** | Inside a Shipping context, an Order (if the term survives the translation at all) means something almost unrelated: a physical parcel with a weight, dimensions, a carrier, a tracking number, and a delivery address - everything needed to answer 'how does this get to the customer's door?'. | A naive design merges these into one 'Order' class with all the fields from both concerns. That model works for a while, but every team's change becomes a landmine for the other team: - Shipping adding an 'estimated delivery date' field might break a Sales report that assumes Order rows never change after checkout. - Sales adding a 'gift wrap' flag has to be threaded through code Shipping never asked for and doesn't care about. This is the concrete failure DDD calls a corrupted or '**polluted**' model, and it's the reason bounded contexts exist: rather than fighting to keep one shared Order model coherent for two unrelated purposes, DDD says let Sales and Shipping each own their own Order concept, fully tailored to their own concern, and treat any translation between the two as an explicit, visible integration step rather than something baked silently into a shared class. ## Why it works Why does this work, mechanically? Because a model doesn't need to be 'true' in some universal sense - it needs to be **useful for the decisions** the people using it are making. A model is a simplification built for a purpose; forcing two different purposes to share one simplification produces a model that serves neither well. By drawing an explicit line and saying 'inside this line, Order means X, and we will never let a Shipping concept sneak in uninvited,' a team gets freedom to evolve their model quickly, because they no longer need cross-team sign-off just to add a field that only they care about. The ubiquitous language - the specific, precise vocabulary the team and its domain experts use in conversation, code, tests, and documentation - is scoped to live inside that same boundary; it is deliberately **not a company-wide glossary**, because a company-wide glossary either becomes so vague it stops being useful, or forces genuinely different concepts into an artificial single definition. ## The trade-off The trade-off is **duplication**: multiple 'Order' concepts now exist across the codebase, and someone unfamiliar with the boundary might initially see this as waste or inconsistency. DDD accepts this cost deliberately, because the alternative - one shared model contorted to satisfy every consumer - produces far worse coupling: - any team's change can silently break any other team's assumptions; - testing the whole thing becomes combinatorial; - nobody can reason locally about what a change will do. The cost of duplicated, boundary-scoped concepts is much cheaper to manage (it's visible, local, and each copy can be simple) than the cost of hidden coupling through one shared '**God model**.' ## How the missing boundary shows up In production, failing to recognize you need a bounded context shows up as a specific pattern: 1. a core entity class or table that keeps growing fields nobody can safely delete; 2. tests that break in one team's suite because of another team's unrelated change; 3. deploys that get delayed because two teams' work landed in the same shared model and now must be reconciled together. Recognizing this early - and drawing the boundary deliberately rather than letting it accrete by accident - is the practical value bounded contexts deliver.

  • If two teams both need to talk about 'the same' Order, how do they communicate without merging their models into one?
    They define an explicit translation at the boundary - typically a small integration layer or an agreed message contract - that maps one context's Order representation to the other's. Each side keeps its own internal model; only the translation code needs to understand both vocabularies. This is often implemented as an Anti-Corruption Layer or a published event schema, so neither team's internal model has to compromise for the other's convenience.
  • Does a bounded context have to correspond to one microservice?
    No - it's a modeling boundary, not a deployment boundary. A single service can house multiple bounded contexts (though that's usually a sign of insufficient separation), and in legacy or monolithic systems one bounded context frequently spans multiple modules or even multiple physical databases. The common convention in modern systems is one service per bounded context, but that's a design choice, not a definitional requirement.
  • What goes wrong if you don't recognize you have two contexts and instead build one shared model?
    You get an ever-growing class or table (often literally called Product or Customer) with fields added by every team for their own purpose, becoming impossible to change safely - any edit risks breaking someone else's meaning. This is the 'big ball of mud' failure mode DDD explicitly names as what bounded contexts prevent.

Think of a bounded context like different departments in a hospital using the word 'chart.' In Nursing, 'chart' means the bedside vitals log updated hourly. In Billing, 'chart' (as in 'chart of accounts') means a ledger structure for invoicing. Same building, same organization, completely different objects called by an overlapping word - and nobody is confused because each department only uses 'chart' inside its own conversations.

saying these in an interview costs you the question

  • says a bounded context is just a database schema
  • claims every system should have exactly one bounded context
  • conflates bounded context with microservice with no caveat
  • thinks duplicating a concept like Order across contexts is a bug to fix by merging models
  • can't explain why the same word can validly mean two different things

context

open as a page

When you're carving a large, tangled domain model into bounded contexts, what concrete signals ('seams') tell you where one context should end and the next begin?

level: middleimportance: must knowfreq 70%

basics

~20 s

Look for places where the same word is used differently, where one team owns a process end-to-end, or where business rules and data change together but not with the rest. Those cracks show where boundaries naturally sit.

open as a page

A Billing bounded context needs data from a legacy Inventory system whose data model uses incompatible concepts (e.g., a single 'SKU status' enum that encodes both stock level and discontinuation). What pattern keeps that legacy model from leaking into and corrupting Billing's own domain model, and how does it work mechanically?

level: seniorimportance: must knowfreq 65%

basics

~20 s

An Anti-Corruption Layer - a translation layer at the boundary that converts the legacy system's data and concepts into Billing's own clean model, so Billing's code never has to understand or depend on the legacy shape directly.

open as a page

When a bounded context needs to expose its model to many other consumer contexts at once, not just one partner team, what integration pattern lets it do so without each consumer coupling directly to its internals, and how does it work?

level: middleimportance: should knowfreq 50%

basics

~10 s

The provider context publishes a stable, well-documented public API and/or event schema (a "published language") that many consumers can integrate against, instead of exposing its internal model directly to each one.

open as a page

Two teams, Checkout and Fulfillment, need to integrate, and Checkout's team is much larger and moves faster than Fulfillment's. What context-mapping relationship patterns describe the possible power dynamics between two integrating bounded contexts' teams, and how do you choose which one to apply?

level: seniorimportance: should knowfreq 55%

basics

~10 s

DDD names relationship types between two teams' contexts - Customer-Supplier (supplier adapts to consumer), Conformist (consumer just accepts supplier's model), Partnership (co-design together) - chosen by relative priority, trust, and negotiating power.

open as a page

A bounded context that started small has grown over two years to encompass Pricing, Promotions, and Tax logic all in one service with one team. What signs tell you it's time to split it into separate bounded contexts, and what risks come with splitting too early versus too late?

level: principalimportance: should knowfreq 40%

basics

~20 s

Split when the team can't reason about the whole model at once, parts change for unrelated reasons, or sub-teams have informally formed. Splitting too early wastes effort on a premature boundary; splitting too late lets coupling keep growing.

open as a page