A bounded context is the explicit boundary inside which a domain model and its vocabulary stay consistent — the same term, like Customer or Order, is guaranteed to mean exactly one thing. Outside that boundary, the same word can mean something else entirely, and that is not a bug to fix but a fact to design around. Most systems that collapse under their own complexity did so because one team tried to force a single model to serve billing, support, and fulfillment at once. Drawing the lines between subdomains well is one of the highest-leverage decisions in any system that outlives its first year.
The core idea
A large domain rarely has one consistent shape. Ask billing what a customer is and you get a billing account with payment terms. Ask support the same question and you get a contact history with open tickets. Neither team is wrong — they need different facts and different rules. A bounded context makes that difference official: inside the billing context, Customer means the billing model; inside support, a translation happens deliberately at the seam, not by accident through a shared database table. The alternative — one shared Customer class serving every team — tends to accumulate fields nobody agrees on until it serves no one well.
Types of subdomains
Not every part of a domain deserves the same investment. Classifying subdomains up front tells you where to spend design effort and where to buy or borrow instead.
| Subdomain type |
What it is |
Investment |
| Core |
The part that makes the business win or lose |
Build carefully, model deeply, keep in-house |
| Supporting |
Necessary but not differentiating |
Build simply, avoid over-engineering |
| Generic |
Solved problems every company has |
Buy, adopt an off-the-shelf tool, or outsource |
A payments startup treats fraud scoring as core and its internal wiki as generic. Misjudging which bucket a subdomain falls into is how teams end up hand-rolling authentication (generic) while their actual differentiator (core) gets a rushed data model.
Context mapping patterns
Once contexts are identified, you need a deliberate strategy for how they talk to each other. These patterns, cataloged in context mapping, describe the realistic options.
| Pattern |
What happens at the boundary |
| Shared kernel |
Two teams deliberately share a small, jointly-owned subset of the model |
| Customer-supplier |
The upstream team commits to meeting the downstream team's needs |
| Conformist |
The downstream team accepts the upstream model as-is, no translation |
| Anticorruption layer |
The downstream team translates the upstream model at the boundary |
| Open host service |
The upstream team publishes a stable interface for many consumers |
| Separate ways |
The teams decide integration costs more than it is worth |
An anticorruption layer is the pattern to reach for whenever you depend on a legacy system or a vendor whose model you do not control and do not want leaking into your own.
How to actually draw the boundaries
- Follow the language, not the org chart. The moment a word changes meaning or a synonym appears, you have found a candidate seam.
- Look for differing rates of change. Parts of the domain that evolve on different schedules rarely belong in one model.
- Check who owns the data. If two teams both need write access to "the same" entity for different reasons, that is a boundary in disguise.
- Map the integration pattern deliberately. Decide shared kernel, conformist, or anticorruption layer on purpose, before code makes the decision by default.
- Expect to redraw lines. Treat the first context map as a draft, not a contract poured in concrete.
Common mistakes
Drawing boundaries around the org chart instead of the language. Two teams that report to the same director do not automatically share a model; splitting by reporting line instead of by meaning just relocates the confusion.
Skipping the anticorruption layer on a "temporary" integration. Temporary integrations with a legacy system outlive every estimate; the layer that translates its model at the edge is what keeps that legacy mess from spreading.
Treating every subdomain as core. Modeling a generic problem — file storage, email delivery, search indexing — as deeply as your actual differentiator wastes the scarce design effort the core subdomain needed.
Confusing a bounded context with a service. A bounded context is a modeling boundary; a microservice is a deployment boundary. Forcing them to always match creates services that split a model in half.
FAQ
Is a bounded context the same thing as a microservice?
No. A bounded context is about where a model's meaning holds; a microservice is about what deploys independently. They frequently line up, but a bounded context can contain multiple services, and a service should never span two contexts.
How big should a bounded context be?
As big as the language stays consistent, and no bigger. There is no target size — shrinking one just to hit a number usually creates awkward, chattier integrations.
What is the fastest way to find hidden boundaries in an existing codebase?
Look for the same noun with two different meanings, or a class with fields that only half its callers ever populate. Both are strong signals that two contexts have been merged into one.
Do small teams need to bother with this?
Lightly. Even a two-person team benefits from noticing that "order" means something different in the cart than in fulfillment; the formal patterns matter more once multiple teams and services are involved.
Where to go next
See API design best practices in 2026 for how these boundaries shape the contracts you expose, what a merge conflict is in 2026 for another kind of boundary friction between teams, and what a git fork is in 2026 for a related way codebases diverge on purpose.