Bounded Contexts Are Not Services
One bounded context does not automatically mean one microservice. Bounded contexts and services solve different problems, and understanding their relationship helps us design systems that are easier to evolve and maintain.
Many people who start their journey with bounded contexts automatically map them to services.
Even though there may be systems where this approach works, it is not a rule. You may find yourself in a situation where services do not reflect bounded contexts one-to-one. And trust me, there is nothing wrong with that.
Bounded contexts and architecture
How come bounded contexts are not the same as services if they are part of the solution space? If they aren't services, why do we need them in the first place? Why introduce yet another concept?
The reason is simple: bounded contexts and services define different boundaries. A bounded context defines the boundary of a domain model and its language, helping us understand the problems we solve and preserve that knowledge. Services, on the other hand, define runtime and deployment boundaries. They help us scale the system, manage interactions over the network, and address other operational concerns.
Bounded contexts help us understand the domain and manage domain knowledge, while services help us address runtime concerns such as resilience and availability.
This means that bounded contexts influence our technical decisions, but they are not tied to a single technical solution. The same bounded context can be represented differently depending on the architecture we choose.
Bounded contexts, microservices, and modular monoliths
Bounded contexts work well with both microservices and modular monoliths because these architectural approaches encourage us to divide a system into distinct areas. Of course, neither using microservices nor building a modular monolith automatically means that you are using bounded contexts. But when you combine these approaches, you can build a system that is easier to evolve and maintain.
These approaches recognize that a system can become too big and complex to be understood and maintained as a single unit. They encourage us to define boundaries so that we can reason about individual parts of the system in isolation.
Using bounded contexts to guide the boundaries within either architecture helps us create services or modules with well-defined, cohesive models. It also helps us establish clear integrations between different parts of the system, with relationships that reflect the domain rather than arbitrary technical divisions.
Using bounded contexts as a driving force when defining services and modules helps protect us from drifting toward a distributed monolith or a Big Ball of Mud.
Bounded contexts and the Big Ball of Mud
Even though bounded contexts can be used with various architectures, it is worth remembering that not every architecture or solution automatically contains well-defined bounded contexts. A system does not become well-structured simply because it has a model or is divided into technical components.
There is an interesting question we can ask ourselves here: every system has a model, whether good or bad. And if a bounded context defines a boundary around a domain model, doesn't that mean every system contains at least one bounded context?
No, this is not necessarily true, because a bounded context requires a model and a ubiquitous language, as explained in detail last time. A Big Ball of Mud often lacks an unambiguous and consistent language. Its model is usually chaotic and disordered. Yes, a model exists, but such a model is hardly useful, and the mere existence of a model does not mean that a meaningful bounded context has been established.
Bounded contexts as guidance
Bounded contexts do not determine the architecture, but they provide valuable guidance. When their boundaries are reflected in the system through service boundaries, modules, or other architectural elements, the system is easier to reason about and change.
Ignoring these boundaries can be harmful in the long run. A single requirement might force you to change multiple places in the system, or you might find yourself maintaining duplicated domain logic across different parts of it.
The goal is not to make every bounded context a separate service. The goal is to preserve meaningful domain boundaries and make deliberate architectural decisions about how to reflect them in the system.
Summary
Bounded contexts and services solve different problems. Bounded contexts help us define and maintain consistent domain models, while services help us organize runtime and deployment responsibilities. Their boundaries can align, but they do not have to. What matters is understanding the domain, defining meaningful boundaries, and making architectural decisions that support the system's evolution rather than blindly mapping every bounded context to a separate service.
Comments ()