Managing Domain Complexity with Bounded Contexts
I’m continuing my way through Learning Domain-Driven Design by Vlad Khononov. Chapter 3’s argument, stripped of jargon: a ubiquitous language is only ubiquitous inside a boundary. Once the business is big enough that the same word means two different things to two different teams, you need more than one language. And where you draw the walls is a design choice, not something the domain hands you.
One Model to Rule Them All Doesn’t
The instinct, when a single concept fragments across the business, is to absorb the fragmentation into a bigger model. One canonical schema. One ERD that spans an office wall. A model that handles every case.
It doesn’t work. Such a model ends up jack of all trades, master of none: suitable for everything, useful for nothing. The cost shows up everywhere: filtering out the bits you don’t need, finding the bits you do, and most of all keeping the data in a consistent state when every team is editing the same surface.
The other naive fix is to prefix the conflicting terms. Marketing lead and sales lead. That gets the two meanings into code, but it has a problem the chapter is sharp about: nobody talks like that. Domain experts don’t say “sales lead” in a meeting; they say “lead,” and they rely on the conversation to disambiguate. The ubiquitous language fractures on contact with conversation, and the prefixes become an engineering-only dialect.
A Language Needs Walls
The bounded context pattern is the answer to both failures. Don’t make one giant language. Make several smaller ones, and give each its own context where it applies. The word lead is allowed to mean two different things, as long as each meaning has a fence around it.
The line I want to remember is that a model is not a copy of the real world. It’s a tool for solving a specific problem. Without a boundary, a model will expand until it tries to become a copy of the real world, at which point it’s useful to nobody.
This matches what I see in practice. The domain models that go bad don’t go bad by being wrong; they go bad by growing. They keep absorbing concerns because nobody owns the wall. A bounded context isn’t really a diagram artifact. It’s an explicit answer to the question “what is this model for?”, and that question is what stops the growth.
Discovered vs. Designed
The cleanest distinction in this chapter is the one between subdomains and bounded contexts. Subdomains are discovered: they already exist in the business, and the engineer’s job is to recognize them. Bounded contexts are designed: the engineer decides where to draw the walls, based on team shape, technical constraints, and which models need to stay internally consistent.
A one-to-one mapping between the two is fine when the subdomain is small and coherent. But it isn’t required, and it isn’t always the best choice. One subdomain can host several bounded contexts when there’s genuine value in modeling the same concept multiple ways: different maps of the same planet, each tuned to a different question.
Where I’ve seen teams get this wrong is the conflation: treating bounded contexts as if they too were discovered, and then drawing them along whatever lines the org chart already drew. Bounded contexts end up shaped like the company instead of like the problem, and you can feel it in the integration costs afterward.
The Wall Is Physical, Too
A bounded context isn’t only a modeling fence. It’s a deployment fence and an ownership fence. Each one is its own service, its own repo, its own release cycle, free to pick the stack that fits its problem. And each one is owned by exactly one team, even if a single team owns several.
The line that lands hardest is the old saw about good fences making good neighbors. The bounded context is where the actual seams of the system run: code, deploys, and people. A bounded context that two teams co-own isn’t a bounded context. It’s a shared mess with a name.
The boundary is the model. A model without a wall isn’t a smaller copy of reality; it’s an aspirational one, and the aspirational ones lose to the bounded ones every time.
Onward to chapter 4, where the question becomes: once these contexts exist, how do they talk to each other without leaking back into a single giant model?
Part of the Learning Domain-Driven Design series.