Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.
Logical boundaries aren’t physical boundaries. A service boundary can be a one-to-one mapping of logical boundary and physical boundary but they don’t have to be. A logical boundary can have many physical boundaries and a physical boundary can be composed of many components from many logical boundaries. Do we have microservices to thank for the idea that the physical, development, and logical views are the same? This introduces a pile of unneeded complexity related to deployment, versioning, and data duplication.
YouTube
Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything in this post.
Physical & Logical Boundaries
When most people think of service boundaries, they are often thinking of this diagram below. The dotted line represents a service boundary, in which both services communicate has their own database, however, they communicate directly with each other.
Now if I were to specifically call out physical boundaries, I would have illustrated with a dotted line that the databases are a physical aspect separately from the service itself.
This is pretty obvious as each service is probably making network calls to a database instance.
So now let’s throw some Client/UI into the mix. How would that fit into the diagram illustrating physical boundaries? It may look something like this:
However, in my experience, most folks aren’t building a dedicated UI/Client for each service, rather they often build a SPA, maybe a mobile app, etc.
Now I’m excluding an API gateway or BFF (Backend for frontend) in this diagram, but that could exist as well, in which the Client/UI would communicate with that, and it in turn would communicate with the various services.
What I’m really illustrating here is the idea that there is usually a frontend and a backend. The backend is represented by possibly many different services.
Based on the diagram, if I were to ask how many logical boundaries there are, you would likely say 3. If you are, it’s because you’re assuming my illustrating of logical boundaries is also represented in the same way as physical boundaries. The dotted lines represent physical boundaries, not logical boundaries. However, our industry has standardized physical boundaries being the same as logical boundaries. While they can be, they don’t have to be.
Service Boundaries
What’s a service? What are its boundaries?
A service is the authority of a set of business capabilities.
Behind those capabilities are the data that it owns. It’s a grouping of functionality that serves the business. Notice I have said nothing about technology? How you choose to develop and physically deploy those capabilities has nothing to do with defining a logical boundary.
So if we take the earlier diagram, and outline what the logical boundaries are, they are now vertical, not horizontal.
A portion of the UI is owned by a local service boundary. The UI, the actual behaviors and capabilities, and the data all together define the logical boundary.
The issue is that there are multiple different ways to view a system. Below is a diagram that illustrates the 4+1 Architectural View Model by Philippe Kruchten
Without going into full detail about what each view represents, what I’ve been illustrating is that the logical view and physical views can be different. They do not have to be exactly the same.
If you were to think of a typical microservices implementation, the logical view and physical view are often the same. And if you’re not using a mono-repo, and have a git repo per each service, you then likely have the logical, development, and physical views all exactly the same.
A service boundary should own the entire vertical. This is why the UI is included when I’m illustrating the logical boundaries. The frontend isn’t its own logical service.
This means that you can deploy your logical boundaries in many different ways. As an example of physical boundaries, you could have a UI that’s composed of multiple logical boundaries. The actual Service API could be composted together into a single process/container. A single database instance could hold the schema and data for each logical service boundary.
So if we again jump back to the logical view, this turns into slicing everything vertically.
Why does it matter?
So who cares? What’s the big deal if we treat physical boundaries as local boundaries? Unneeded complexity.
Boundaries are hard to define. When you focus on business capabilities and not technical concerns, you have to get deeper insights into the actual business domain. Understanding the capabilities that a service must provide and the data ownership behind those capabilities isn’t trivial to figure out.
If you treat local boundaries and physical boundaries as being the same thing, and you get these capabilities wrong (which you likely will), you’ll end up doing a lot of service-to-service communication, likely over a network via RPC. This path leads you to a distributed monolith, that is often worst than a traditional monolith. For more on this specifically, check out my post: REST APIs for Microservices? Beware!
A distributed monolith can be horrific because you’ll lose consistency if you really need it when performing commands. If you’re reaching out over RPC to another service boundary to get data to perform a command, the moment you get that data it’s inconsistent/stale. There is no distributed transaction.
Another issue is versioning and deployment. If you make a change to a service, but need all other services to make the appropriate changes as well, and they all need to get deployed together, you’re losing one of the primary benefits. You lost the ability to do independent deployments. Your services aren’t autonomous.
Logical boundaries do not need to be physical boundaries. They can be, but they do not have to be. You can have multiple services that are all composed and deployed in the same process. They could all live within the same git repo. Should you do this? Maybe that is actually best in your context. Maybe it’s not. But don’t get stuck thinking they’re the same thing.
Defining logical boundaries is hard. You’ll likely get it wrong. If you’re developing a new system and are unsure of where boundaries may lie, don’t put the added constraints of making your logical and physical boundaries the same as it will be much more difficult to change and manage.
Join!
Developer-level members of my YouTube channel or Patreon get access to a private Discord server to chat with other developers about Software Architecture and Design as well as access to source code for any working demo application that I post on my blog or YouTube. Check out the YouTube Membership or Patreon for more info.