Evolutions of Services that restructure services
Services work well when each service matches a subdomain and is developed by a single team. If those premises change, you’ll need to restructure the system:
- A new feature request may emerge outside of any of the existing subdomains, creating a new service.
- A service may grow too large to be developed by a single team, calling for division.
- Two services may become so strongly coupled that they fare better when merged together.
- The entire system may need to be glued back into a Monolith if domain knowledge changes or interservice communication strongly degrades performance.
- Alternatively, coupled services may be clustered into co-deployed Cells to reduce operational complexity.
Add or split a service#

Patterns: Services.
Goal: get one more team to work on the project, decrease the size of an existing service.
Prerequisite: there is a loosely coupled (new or existing) subdomain that does not have a dedicated service (yet).
If you need to add a new functionality that does not naturally fit into one of the existing services, you may create a new service and maybe get a new team for it.
If one of your services has grown too large, you should look for a way to subdivide it (likely through a Sandwich stage with a shared Orchestrator and database) to decrease the size and, correspondingly, complexity of its code and get multiple teams to work on the resulting (sub)services. However, that makes sense only if the old service is not highly cohesive – otherwise the resulting subsystem may be more complex than the original service.
Pros:
- You get an extra development team.
- The complexity of the code decreases (splitting an existing service) or does not increase (adding a new one).
- The new service is independently scalable.
Cons:
- You add to the operations complexity by creating a new system component and several inter-component dependencies.
- There is a new point of failure, which means that bugs and outages become more likely.
- Performance (or at least latency and cost efficiency) of the system will deteriorate because interservice communication is slow.
- You may have a hard time debugging use cases that involve both the old and new service.
Merge services#

Patterns: Services, Monolith or Layers.
Goal: accept the coupling of subdomains and improve performance.
Prerequisite: the services use compatible technologies.
If you see that several services communicate with each other almost as intensely as they call their internal methods, they probably belong together.
If your use cases have too high a latency or you pay too much for CPU and traffic, the issue may originate with the interservice communication and merging the services should help. No services, no pain.
Alternatively, as domain knowledge changes [DDD], you may have to merge much of the code together only to subdivide it later along updated subdomain boundaries. Which means you face lots of work for no reason.
Pros:
- Improved performance.
- It becomes easy for parts of the merged code to access each other and share data.
- The new merged service or Monolith is easier to debug than the original Services.
Cons:
- The development teams become even more interdependent.
- There is no good way to vary qualities by subdomain.
- You lose granular scalability by subdomain.
- The merged codebase may be too large for comfortable development.
- If anything fails, everything fails.
Cluster services#

Patterns: Cell (Hexagonal Architecture, Services).
Goal: reduce operational complexity, decouple subdomains, and improve performance.
Prerequisite: there are distinct subdomains.
When there are too many services, none sees the big picture: which components are involved in a use case and why the system world the way it does. Moreover, managing tens to hundreds of different services and databases is hard and error-prone.
Therefore cluster services that share a subdomain into a co-deployed cohesive Cell.
Pros:
- Managing ten Cells is much easier than a hundred services.
- More clear and independent subdomains as their interdependencies become explicit.
- Lower traffic as closely communicating services are now co-located.
- Lower data storage requirements as the contents of a Cell may share a database.
- No boilerplate code for versioning or data views inside a Cell.
Cons:
- The development teams that work on services that belong to a single Cell need to synchronize their actions.
- A Cell is usually scaled as a whole.
Further steps:
- Complete Cell encapsulation through the use of Adapters and Ambassador Plugins.
- Transform any strongly coupled Cells into Sandwiches.