THIS EXPLANATION
THE ROOM
CDA·20 Computing, Data & AI 7 MIN · 8 STATIONS

Bounded contexts

A Socratic walk-through of bounded contexts — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

Why should the same word be allowed to mean different things in different parts of one system?

Every instinct in data modelling says one word should mean one thing. Define Customer once, use it everywhere, and the system stays coherent; let two teams define it twice and you have a mess of duplication and drift. This is close to an article of faith, and it is why "single source of truth" is one of the least-questioned phrases in the field.

So consider what happens when you actually try it. Sales says a customer is a lead with a pipeline stage and an owner. Shipping says a customer is an address with delivery constraints. Billing says a customer is a legal entity with a tax jurisdiction and a payment history. Support says a customer is whoever is on the phone. Unify them and you get one class with sixty fields, three-quarters of them null for any given instance, and a room full of people who cannot finish a sentence about it. Was the instinct wrong — or was it right about something narrower than we thought?

b

Reasoning it through

REASONING #

Notice first what those four definitions actually are. Not four sloppy attempts at one concept, but four correct concepts that happen to share a word, because each department abstracts away everything irrelevant to its work. Shipping ignores tax jurisdiction not from negligence but because delivery does not depend on it. That is what a model is for: a deliberate simplification aimed at a purpose. A model with no purpose has nothing to guide what it leaves out, which is why the unified class grows without limit.

So the trouble is not two definitions of a word. It is one definition serving two purposes. Ask which is more expensive: the duplication of maintaining two Customer types, or the coupling of a single type that four teams must all agree to change? The duplication cost is roughly constant. The agreement cost grows with the number of parties and their rate of change — and it lands on every change, not just the ones that concern everybody.

There is a subtler cost too. When a word's meaning is stretched across purposes, conversation degrades in a way nobody notices: two engineers say "customer", both understand themselves perfectly, and mean different things, and the misunderstanding surfaces weeks later as a defect nobody can attribute.

That points at the actual unit of design. It is not the word and not the class — it is the boundary within which a word has exactly one meaning. Eric Evans called that a bounded context in his 2003 book on domain-driven design, and the language it protects the ubiquitous language: one vocabulary shared by the developers and the domain experts of that context, used identically in speech, in documents, and in the names in the code. The boundary is what makes the promise keepable. A language cannot be ubiquitous across an entire enterprise; it can be ubiquitous across a team and its subject matter.

Then a fair objection: if Sales and Billing each have their own customer, how does anything work? They are talking about the same human being. This is where the design gets real rather than philosophical. The contexts must exchange information across the boundary, and every crossing needs an explicit answer to two questions — what identity links the two notions, and who translates.

The identity is usually a shared key that both sides agree carries no meaning of its own. The translation is the piece people skip. Evans catalogued the relationship patterns: a shared kernel where two contexts jointly own a small overlapping model; conformist where a downstream context accepts the upstream's model wholesale because it has no leverage; and an anticorruption layer, a translating shim a context builds at its own edge to keep a foreign model from leaking inward — the honest answer to a legacy system or a vendor API you cannot influence. Drawing these on one page gives you a context map, whose real function is to make explicit which team's meaning wins at each seam and who pays for the translation.

One honest caveat about scope. Bounded contexts are a heuristic for where to put boundaries, not a proof that a boundary is in the right place. Splitting a genuinely single concept into two contexts is a real failure mode — you then spend your life synchronising two models that must always agree, which is worse than the sixty-field class. The test is whether the two sides have genuinely different purposes and vocabularies, or merely different screens.

c

The analogy

THE ANALOGY #
THE FIGURE

Consider the word "bank". In hydrology it is the edge of a river; in finance it is an institution holding deposits; in aviation it is a roll about the longitudinal axis; in snooker it is a cushion shot. Nobody proposes reconciling these into one definition, and no confusion results, because each lives inside a discourse with its own boundary. Confusion arises only when a sentence straddles two of them — and then the fix is not a merged definition but making explicit which discourse you are in.

WHERE IT BREAKS DOWN

those four meanings of "bank" are historically unrelated and never need to be reconciled, whereas your four customers refer to the same person and must be linked — so the analogy captures why separate meanings are legitimate, but not the translation work, which is where the actual engineering effort goes.

d

Clarifying the model

THE MODEL #

The correction worth making carefully: a bounded context is not a synonym for a microservice, and treating them as identical is the most common way this idea goes wrong. A context is a linguistic and modelling boundary. It might be one service, several services, or a well-separated module inside a single deployable — and starting with a well-separated module is usually the better move, because a boundary drawn in the wrong place is cheap to move inside one codebase and expensive to move across a network. The one thing that is reliably true is the reverse: a service that spans two contexts will keep growing conflicting demands, so a context boundary is a strong candidate for a service boundary once it has proved stable.

Two refinements. First, the boundary must be enforced by something or it decays — shared database tables are the classic dissolver, since two contexts reading the same table have merged their models regardless of what the diagram claims. Second, an anticorruption layer is a translation cost accepted deliberately to keep a foreign vocabulary out of your core: the same trade as before, duplication bought to avoid coupling.

e

A picture of it

THE PICTURE #
Bounded contexts
Bounded contexts Read each first-level branch as a separate room with its own door. Inside a room, the vocabulary listed under "Language" is the only one spoken and every word has exactly one meaning; nothing in one branch is required to agree with anything in another. The fourth branch is the only place the rooms touch -- it holds the machinery for crossing, and the fifth branch is what you get if you knock the walls down instead. {"generator":"[email protected]","source":"../Socrates/.diagram-cache/_src/bounded-contexts.md","sourceIndex":1,"sourceLine":4,"sourceHash":"f752ca585f4e6ef2c36966c416676bbf798220e44f027fcbbbde6ac7a4a9bafc","diagramType":"mindmap","layoutVariant":"source","repairedDuplicateIds":[{"original":"mermaid-f752ca585f4e6ef2-0-node_1","replacement":"mermaid-f752ca585f4e6ef2-0-node_1--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_2","replacement":"mermaid-f752ca585f4e6ef2-0-node_2--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_3","replacement":"mermaid-f752ca585f4e6ef2-0-node_3--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_4","replacement":"mermaid-f752ca585f4e6ef2-0-node_4--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_5","replacement":"mermaid-f752ca585f4e6ef2-0-node_5--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_6","replacement":"mermaid-f752ca585f4e6ef2-0-node_6--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_7","replacement":"mermaid-f752ca585f4e6ef2-0-node_7--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_8","replacement":"mermaid-f752ca585f4e6ef2-0-node_8--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_9","replacement":"mermaid-f752ca585f4e6ef2-0-node_9--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_10","replacement":"mermaid-f752ca585f4e6ef2-0-node_10--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_11","replacement":"mermaid-f752ca585f4e6ef2-0-node_11--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_12","replacement":"mermaid-f752ca585f4e6ef2-0-node_12--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_13","replacement":"mermaid-f752ca585f4e6ef2-0-node_13--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_14","replacement":"mermaid-f752ca585f4e6ef2-0-node_14--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_15","replacement":"mermaid-f752ca585f4e6ef2-0-node_15--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_16","replacement":"mermaid-f752ca585f4e6ef2-0-node_16--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_17","replacement":"mermaid-f752ca585f4e6ef2-0-node_17--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_18","replacement":"mermaid-f752ca585f4e6ef2-0-node_18--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-node_19","replacement":"mermaid-f752ca585f4e6ef2-0-node_19--duplicate-2"},{"original":"mermaid-f752ca585f4e6ef2-0-gradient","replacement":"mermaid-f752ca585f4e6ef2-0-gradient--duplicate-2"}],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":1201,"height":633},"qa":{"passed":true,"findings":[]}} The word customer Sales context Lead with a pipeline stage Owned by a named rep Language: prospect,qualify, close Shipping context Delivery address andaccess notes Route and time window Language: consignment,drop, attempt Billing context Legal entity and taxjurisdiction Credit terms and paymenthistory Language: invoice,dunning, settle Crossing the boundaries Shared identifier carriesno meaning Anticorruption layertranslates inward Context map names whoowns each seam The failure it avoids One class with sixtymostly null fields Every change needs fourteams to agree

How to readRead each first-level branch as a separate room with its own door. Inside a room, the vocabulary listed under "Language" is the only one spoken and every word has exactly one meaning; nothing in one branch is required to agree with anything in another. The fourth branch is the only place the rooms touch — it holds the machinery for crossing, and the fifth branch is what you get if you knock the walls down instead.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

The rule "one word, one meaning" is right, but its scope was never the whole enterprise — it holds inside a boundary drawn around a shared purpose. Different purposes legitimately abstract the same real thing differently, so the design work is not choosing the winning definition but placing the boundaries and paying explicitly for the translation between them.

g

Where to go next

ONWARD #
  • How to decide whether an emerging seam should stay a module boundary or become a deployment boundary, and what evidence should force the move.
  • Whether event-carried state transfer is a form of anticorruption layer or a way of avoiding one.
h

Key terms

TERMS #
TermWhat it means
Bounded contextan explicit boundary within which a model applies and each term has exactly one meaning.
Ubiquitous languageone vocabulary shared by developers and domain experts within a context, used identically in speech, documents, and code.
Anticorruption layera translation layer a context builds at its own edge so a foreign model cannot leak into its core.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4