Bounded Context
An insightful article exploring domain-driven design through clear explanations of ubiquitous language, bounded contexts, and upstream/downstream relationships.
It was agreed that Ubiquitous Language must be consistently practiced within SHELF. Frank and Katie began to pay close attention to Peter’s vocabulary and corrected him when necessary. DDD started to settle in. But (there’s always a “but”) this was only the beginning. All those models built using the Ubiquitous Language, like everything else, need a place to live.
Divide and Conquer
There’s rarely one big shared universe where all models coexist peacefully. More often, it’s a chaotic mix of Core, Supporting, and Generic Subdomains. Managing that mess is nearly impossible.
To make matters worse, the same term can have different meanings in different Domains. For example: a “book” may be a product for sale in the Store Context. But the same word can also refer to demo copies sent by editors, which fall under the Acceptance Context. These demo books can’t be sold and must be returned. Same term, different meanings, different rules.
This is where the Bounded Context (BC) shines. It defines a boundary where the Ubiquitous Language remains consistent. That’s why it’s called Bounded. It provides a clear, safe space for models shaped by a shared language. A Bounded Context should be:
- explicit about the model and language it owns
- protected from accidental model leaks from other Contexts
- integrated with other Contexts through deliberate contracts
A Bounded Context can be implemented inside a modular monolith, a separate service, or even a team boundary before it becomes a deployment boundary. As your system grows and a monolith starts becoming a bottleneck, a well-isolated Bounded Context is a strong candidate to be extracted into a microservice. If the architecture is clean, the transition is much less painful. It’s wise to use code quality tools to detect “leaks” between Contexts early and avoid technical debt.
Blueprints
Let’s visualize the Bounded Contexts in SHELF. There’s a Stationery Store where Buyers pay cash or use cards. There’s also an Online Store with digital payments. Books in both stores must first be available in Storage. Storage, in turn, depends on Acceptance, where Frank handles incoming demo books, reviews, and shipping.
Buyers can also post Reviews, but only for books that are actually in the system. When you think about it, it’s more complex than it first appears. Below is a diagram showing Bounded Contexts for SHELF’s Core Domain: selling books.
SHELF bounded contexts
+------------------+
| Acceptance |
| demo books |
| reviews intake |
+---------+--------+
|
v
+------------------+
| Storage |
| available books |
| stock rules |
+----+--------+----+
| |
v v
+----------------+ +----------------+
| Stationery | | Online Store |
| cash/card sale | | digital sale |
+----------------+ +-------+--------+
|
v
+----------------+
| Reviews |
| buyer reviews |
+----------------+
The most critical Context is Acceptance. If a cookbook isn’t accepted by Frank, it won’t enter Storage. If it’s not in Storage, it can’t be sold. And without something to review, no Review can be posted. Everything begins with Acceptance.
How Contexts Come Together
In reality, Bounded Contexts are not completely autonomous. Vocabulary and responsibilities may overlap, causing confusion. Don’t let that stop you, take time to study your Domains and Subdomains. You’ll likely notice that most BCs relate to one another in one of two ways: Upstream or Downstream.
Think of a river. It has a source (Upstream) and a mouth (Downstream). Water flows from the higher source to the lower mouth. If you block the river near the mouth, the source remains unaffected. But if the source dries up, the entire river disappears. The same principle applies to BC relationships. Here’s an updated diagram with stream-wise relationships:
Upstream and downstream relations
Acceptance -> Storage -> Stationery Store
\
-> Online Store -> Reviews
Upstream changes flow right.
Downstream contexts adapt to the language and rules they consume.
You can now see how each Bounded Context depends on the others. For instance, Storage depends on Acceptance but is also required by both Stores. Remove Acceptance, and the rest collapse. Remove the Online Store, and the business still runs.
Pros and Cons
Let’s focus on Acceptance and Storage. Two dev teams are assigned: Team A handles the Upstream (Acceptance), Team B the Downstream (Storage). Which team has the advantage?
Team A (Upstream) enjoys independence. They can move fast without worrying much about others. But there’s a risk: poor decisions in Acceptance will ripple down and hurt Storage. Eventually, Downstream may push back and impose constraints on Upstream. That’s not ideal.
Team B (Downstream) has a harder time. They must constantly adapt to changes from Acceptance. They have to watch for breaking changes and maintain backward compatibility. It’s tough. But there’s a silver lining - if their Context is the last in the chain, they can evolve freely without worrying about others depending on them.
Summary
There’s no single best place to be - Upstream or Downstream. It depends on the people involved and the trade-offs they’re willing to accept. Some prefer leading with autonomy, others are comfortable adapting with flexibility. Ideally, let teams choose what suits them best.