skip to content

Boundaries from Bounded Contexts

Using DDD as the tool for boundary-drawing: one bounded context per service, its own ubiquitous language, and a context map showing how contexts relate. It is the standard answer when an interviewer asks how you decide what belongs in a service.

part ofMicroservices architectureoverview, primer and where to startread it →
on this pageshow

questions

5

In microservices design, why do teams typically draw each service's boundary around a Domain-Driven Design 'bounded context' rather than around a database table or an org-chart team?

level: juniorimportance: must knowfreq 75%

answer

  1. one word, one meaning per context
  2. aggregate stays in one service
  3. event storming finds seams
  4. Conway's Law working for you

basics

~20 s

A bounded context is the area of the business where a word like "Order" has exactly one meaning. Building a service per bounded context keeps each service's data model and vocabulary consistent, instead of forcing every team to agree on one giant shared meaning for every term.

solid answer

~50 s

A bounded context is the linguistic and model boundary within which a term (Order, Customer, Product) has one unambiguous meaning and one consistent data shape. Aligning a service boundary to a bounded context means the service owns its own model, database schema, and vocabulary end-to-end, so internal changes never leak into or get vetoed by another team. Splitting by database table instead produces services that share a conceptual model but disagree on meaning, forcing distributed transactions and constant cross-team schema negotiation. Splitting purely by org chart risks boundaries that drift whenever the org reshuffles, and ignores where the actual semantic seams in the domain are. Bounded-context alignment is preferred because it makes the service boundary a stable, semantically-motivated seam rather than an accidental one, minimizing the coordination needed between teams (Conway's Law working for you, not against you).

go deeper

for a junior

Should be able to state that a bounded context is where a term has one consistent meaning, and give a plausible example of the same word meaning different things in two parts of a business.

for a middle

Should additionally explain event storming (or an equivalent discovery technique) as a way to find context boundaries, and know that an aggregate must live wholly inside one service.

for a senior

Should discuss the trade-offs between bounded-context, data-centric, and org-chart decomposition, and describe concrete drift/failure signals (naming collisions, cross-team contention) that indicate a boundary has gone stale.

for a principal

Should reason about how boundaries evolve over a system's lifetime, when to deliberately re-draw them (splitting or merging services as the domain understanding matures), and how to keep decomposition decisions reversible early on to avoid premature ossification.

## What a bounded context is In Domain-Driven Design, a **bounded context** is the explicit boundary within which a domain model and its vocabulary — the *ubiquitous language* — are internally consistent and unambiguous. Outside that boundary, the same word can legitimately mean something else. `Order` inside a **Sales** context might mean a cart of SKUs with pricing and promotions applied; the same word inside a **Fulfillment** context means a set of items to be picked, packed, and shipped from a specific warehouse; inside a **Billing** context it means a line-itemized invoice with tax and payment terms attached. These are not three views of one shared `Order` object — they are three different models that happen to share a name and a loose real-world correspondence. DDD's insight is that trying to force one canonical `Order` entity to satisfy all three consumers produces a bloated, constantly-contested model that nobody owns cleanly. ## Mapping one context to one service When decomposing a monolith (or greenfield system) into microservices, mapping one service to one bounded context lets each service own its model, schema, and language end-to-end without needing sign-off from other teams to evolve it. The mechanism for finding these boundaries is usually collaborative: 1. **Event storming sessions** surface the domain events, commands, and actors in a business process. 2. **Clusters of tightly-related events/entities** that share vocabulary and change together reveal where a bounded context (and thus a candidate service) begins and ends. 3. **Aggregates** — DDD's transactional consistency boundary — are then assigned wholly to one service; you never split a single aggregate's invariants across two services, because that reintroduces the very ambiguity bounded contexts exist to remove. ## The alternatives, and why they are weaker The alternative decomposition strategies are tempting but weaker. - **Splitting by database table** (a *data-centric* decomposition) produces services whose boundaries follow storage convenience rather than meaning — you end up with an *Orders service* and a *Customers service* that both need to agree on a shared, brittle definition of what an order or customer is, and every schema change becomes a cross-team negotiation. - **Splitting purely by org chart** (team ownership) can work when the org structure already reflects real domain seams, but org charts reshuffle for reasons that have nothing to do with the domain — a reorg can silently fracture a bounded context across two teams, or merge two contexts that should stay separate, without anyone noticing until integration pain shows up. ## The trade-off The trade-off of bounded-context alignment is **upfront cost**: finding the real seams requires real domain modeling effort (event storming workshops, talking to domain experts, iterating on the ubiquitous language) before writing a service. Teams that skip this and guess at boundaries from technical intuition alone often draw them in the wrong place: - **Too fine-grained** — chatty, coupled services that always deploy together, a *distributed monolith*. - **Too coarse** — a service that silently straddles two bounded contexts and re-introduces the ambiguous, contested model DDD was meant to prevent. The upside, when done well, is that each service boundary is a genuine semantic seam: changes inside one bounded context rarely ripple into another, so teams can evolve their service's internal model freely as long as they honor the translation contract (an anti-corruption layer or explicit context map) at the boundary. ## Failure modes Failure modes show up gradually rather than immediately. A service that was cleanly one bounded context at launch can drift as new features get bolted onto whichever service is *closest* rather than where the domain seam actually is — for example, adding loyalty-points logic to the Order service because it's convenient, when loyalty really belongs to its own context with its own rules and lifecycle. Over time this produces a service that speaks two ubiquitous languages internally, with naming collisions and a schema that no longer maps cleanly to any one mental model — a strong signal that the service needs to be split along the (now-clearer) context boundary. ## Where it shows up A concrete real-world pattern is the classic e-commerce decomposition. Catalog, Sales/Cart, Order Fulfillment, Billing/Invoicing, and Shipping are commonly separate bounded contexts and separate services, each with its own notion of `Order` or `Item`, stitched together via published domain events (`OrderPlaced`, `OrderShipped`) and explicit translation at each boundary, rather than one shared Order table queried by five services.

  • What concrete signal in a codebase tells you a service has drifted to cover two bounded contexts instead of one?
    A common tell is naming collisions or a term that means two different things depending on which part of the code you're in — e.g. 'Item' meaning a catalog SKU in one module and a cart line in another within the same service. Another signal is that two feature teams keep stepping on each other's changes to the same entity for unrelated reasons, or the entity has accumulated optional fields that only make sense for one of the two 'contexts' hiding inside it.
  • How do event storming sessions concretely help locate bounded context boundaries before you've written any code?
    Domain experts and engineers place sticky notes for domain events (e.g. OrderPlaced, PaymentCaptured) in time order across a wall, then group related commands and entities around clusters of events that share vocabulary and tend to change together. Gaps or handoffs between clusters — where one group's events trigger the next group's process but use different terms — are where a bounded context boundary, and therefore a candidate service boundary, likely sits.
  • Why is it dangerous to split an aggregate's data across two microservices even if it seems to reduce coupling?
    An aggregate defines a transactional consistency boundary — its invariants must hold true at the end of every transaction, and that only works if all its state is committed atomically in one place. Splitting it across two services turns a single ACID transaction into a distributed one, forcing you into sagas or eventual consistency just to enforce a rule the aggregate was designed to guarantee instantly.

Like separate hospital departments (Billing, Pharmacy, Radiology) that all use the phrase 'patient record' but mean a different subset of data by it — each department keeps its own filing system and translates at the door, instead of fighting over one shared master file that nobody can change without everyone else's approval.

saying these in an interview costs you the question

  • Treats bounded context as just a synonym for 'microservice' with no mention of ubiquitous language
  • Proposes splitting services by database table without discussing meaning/vocabulary
  • Doesn't mention that org-chart-driven splits can drift from real domain seams
  • Can't explain what makes a boundary 'wrong' after the fact
  • Assumes one shared canonical model (e.g. one 'Order' entity) should be used by every service

context

open as a page

When mapping Domain-Driven Design aggregates onto microservice boundaries, why must a single aggregate always live entirely within one service, and what breaks if you split one across two services?

level: middleimportance: must knowfreq 65%

basics

~20 s

An aggregate is a group of objects that must stay consistent together, like an order and its line items. If you split it across two services, you can't guarantee both parts update together, so the data can end up in an invalid, inconsistent state.

open as a page

Two microservices, each aligned to its own bounded context, need to integrate — one is the 'upstream' source of a concept, the other 'downstream' consumes it. What DDD context-mapping patterns describe how the downstream service should protect its own model from the upstream one, and when would you pick each?

level: seniorimportance: must knowfreq 55%

basics

~20 s

When one service depends on another's data, you can either just copy the upstream's model as-is (fast but fragile), or build a small translation layer that converts it into your own local model (more work but protects you from their changes). DDD calls these patterns things like "Conformist" and "Anti-Corruption Layer."

open as a page

The usual advice is 'one bounded context maps to one service.' Under what circumstances is it reasonable to run several bounded contexts inside a single service, or conversely to split one bounded context across several services, and what risk does each deviation carry?

level: seniorimportance: should knowfreq 50%

basics

~20 s

Sometimes it's fine to put two related but minor business areas in one service if they're small and rarely change, to avoid running lots of tiny services. But splitting one business area's logic across several services usually causes trouble, because it breaks up something that should stay together.

open as a page

Two years after a DDD-based microservice decomposition, a Pricing service and a Promotions service constantly deploy together, share a hidden 'effective price' concept neither fully owns, and any change to one breaks the other's tests. As the architect asked to fix this, what diagnostic would you run, and how would you decide whether to merge them, redraw their boundary, or introduce a formal translation layer?

level: principalimportance: should knowfreq 40%

basics

~20 s

When two services always break together, it usually means they were never really separate business areas to begin with, or the line between them was drawn in the wrong place. You'd look at what concept they secretly share, then either merge them back into one service, move the shared idea fully into one of them, or add a clear translation step between them.

open as a page