How do bounded contexts (from Domain-Driven Design) inform where you draw microservice boundaries, and what concrete symptoms show up when a service's boundary crosses into a neighboring bounded context?
answer
- one service ↔ one bounded context
- context map before service map
- anti-corruption layer at seams
- same word, different meaning = boundary
- shared DB table = crossed boundary signal
basics
~20 sA bounded context is where one business term has one consistent meaning (e.g., 'Customer' differs between Billing and Support). Match each service to one context; crossing that boundary causes inconsistent meanings and constant translation code between services.
solid answer
~50 sIn DDD, a bounded context is the boundary within which a specific domain model and its terminology hold consistent meaning. Applied to microservices, the rule of thumb is one service per bounded context (sometimes one context spans a few tightly related services, but never the reverse): a service shouldn't straddle two contexts, and a context shouldn't be split across many services that must stay in lockstep. When a boundary is drawn wrong, symptoms show quickly: a 'Customer' field in one service subtly means something different than in another, requiring translation/anti-corruption layers everywhere they interact; changes to one context force sympathetic changes in another because they share an internal model; and teams start arguing about 'the one true Customer schema' instead of each owning a context-specific view. Getting this right up front is why context boundaries, not database normalization, drive service boundaries.
go deeper
Should be able to explain in plain terms why 'Customer' might mean different things in different parts of the system and why that's not automatically a bug.
Should be able to look at a rough context map and propose service boundaries from it, including calling out where a proposed service straddles two contexts.
Should design the integration between contexts — events vs anti-corruption layers vs shared identifiers — and defend duplicated-looking models as intentional.
Should be able to arbitrate a real cross-team disagreement about 'whose Customer is canonical,' and set an organizational pattern, such as context map governance or event contract ownership, that scales past one team.
## What a bounded context is **Bounded context**, a term from Domain-Driven Design, denotes the boundary within which a particular domain model and its vocabulary carry one consistent meaning; outside that boundary, the same word can mean something else entirely without it being an error. Applied to microservices decomposition, the practical rule is: - each service should sit inside exactly one bounded context; - and while one context can occasionally span a small, tightly related cluster of services, a single service should never straddle two contexts. ## How you apply it The mechanism for using this in practice starts with a **context map** — usually produced through domain discovery work with the people who run the business, not derived from an ER diagram — that names each context and the words that belong to it. For each candidate service boundary, you then ask a concrete test: does this service's internal model stay consistent, with every term meaning exactly one thing throughout? If a proposed `'Customer'` service tries to serve both the billing team's notion of a paying account and the support team's notion of a person with tickets, that's a sign the service actually spans two contexts and should be split along that seam, with each half getting its own model. ## Why it exists This exists to solve a very specific coupling problem: without an explicit context-aware boundary, teams default to drawing service lines around convenient technical artifacts — a database table, an existing module folder, an org chart division — none of which reliably tracks where the business's own conceptual boundaries actually are. When the service boundary doesn't match a bounded context, two services end up implicitly sharing one underlying model even though they're deployed separately, and every difference in how that model needs to evolve on each side becomes a cross-team negotiation. Aligning services to bounded contexts front-loads that negotiation into an explicit modeling exercise instead of letting it leak out as ongoing coordination overhead. ## The trade-off The trade-off is genuine effort spent upfront, and a result that can look wasteful to someone unfamiliar with the reasoning: you might end up with 'Customer' modeled three separate times, once each in Billing, Support, and Marketing services, each with different fields, different validation rules, and no single canonical schema. Teams new to this often push to unify these into 'one Customer service' to reduce apparent duplication — but that reintroduces the very coupling the split was meant to avoid, because now a change driven by Marketing's needs (adding a loyalty-tier field) forces a deploy and review cycle involving Billing and Support too, even though it has nothing to do with either. The cost of doing this right is **discipline**: someone has to keep re-explaining why 'three Customers' isn't duplication, and building the connective tissue (shared identifiers, integration events, anti-corruption layers) between them takes real engineering time that a shared-table shortcut would skip. ## Symptoms of a crossed boundary When boundaries cross a context anyway, the symptoms show up quickly and concretely. - You'll see services querying another team's database tables directly to work around an API that doesn't expose what they need — a sure sign the two are really one model split in two. - You'll see a field whose meaning silently differs between two services (an 'active' flag meaning 'has a valid subscription' in one place and 'logged in within 30 days' in another) causing subtle bugs whenever data crosses the boundary without translation. - You'll see repeated, contentious meetings about 'whose schema is the real one,' and a service that keeps absorbing unrelated responsibility because it was cast as the system's canonical owner of a widely-used noun. ## A worked example A concrete way this plays out: an online retailer separates its Sales bounded context from its Fulfillment bounded context and its Billing context, and each gets its own `Order`: | Context | What an `Order` is there | |---|---| | Sales | a priced, promised set of line items | | Fulfillment | a physical pick-pack-ship workflow | | Billing | an invoiced, collected amount | Each context gets its own service and its own local 'Order' representation scoped to what it needs — Sales doesn't track warehouse bin locations, Fulfillment doesn't track payment method. They're connected not by sharing one Order table but through domain events: Sales publishes `OrderPlaced`, which Fulfillment and Billing each consume and translate into their own model through a small **anti-corruption layer**, so an internal restructuring of Sales's Order model never forces a synchronized deploy of Fulfillment or Billing. This is the practical output of context-aligned decomposition: services that can evolve independently because they were never sharing a model in the first place, just a stream of well-defined events at the seam.
- If 'Customer' legitimately means something different in your Billing service and your Support service, is that duplication a problem to fix?No — that's expected and healthy; each service should have its own Customer representation scoped to what it needs (payment methods for Billing, ticket history for Support). Trying to force one shared 'Customer' schema across both is what creates coupling; the fix is a lightweight identity link (a shared customer ID) plus context-specific attributes, not a single unified model.
- What's a practical warning sign in code review that a service boundary has crossed a bounded context?A pull request in one service that requires a coordinated, same-day change in another service to keep a shared field's meaning consistent — or a service directly querying another service's database table instead of going through its API. Both indicate the two services are really sharing one model that's been artificially split.
- How do you handle a business concept, like 'Order,' that genuinely needs to flow through several bounded contexts?Each context keeps its own local representation of Order scoped to what it cares about, and they're connected via domain events (e.g., OrderPlaced, OrderShipped) rather than a shared table or synchronous cross-context queries. An anti-corruption layer in each consuming context translates the event into its own model, so a change to one context's internal Order shape doesn't ripple into the others.
Like translated legal contracts — the word 'consideration' means something precise and different in contract law than it does in everyday speech. You don't force one glossary to serve both audiences; you keep separate glossaries (contexts) and translate deliberately at the point where the two conversations meet.
saying these in an interview costs you the question
- Proposes one canonical 'Customer' or 'Order' database shared across services as the fix for duplication
- Treats bounded-context alignment as optional busywork and defaults to splitting by database table
- Cannot describe what an anti-corruption layer is for when two contexts need to exchange data
- Assumes seeing the same noun (e.g. 'Product') in two services always means the model should be unified