view as markdownreport a mistake

Evolutions of a Monolith that make Services

type: source-page
updated: 2026-07-02
status: imported
namespace: software-architecture-metapatterns
Imported source page from Denys Poltorak's Architectural Metapatterns wiki. Source path: Appendices/Evolutions of architectures/Evolutions of a Monolith that make Services.md.

The final major drawback of Monolith is the cohesiveness of its code. The rapid start of development begets a major obstacle for project growth: every developer needs to know the entire codebase to be productive, and changes made by individual developers overlap and may break each other. Such distress is usually solved by dividing the project into components along subdomain boundaries (which tend to match bounded contexts \[DDD\]). However, that requires a lot of work, and good boundaries and APIs are hard to design. Thus many organizations prefer a slower iterative transition.

In Services a single component executes a client request while in Pipeline there is no use case owner.

Divide into Services

A monolith is subdivided into services.

<ins>Patterns</ins>: Services.

<ins>Goal</ins>: facilitate development by multiple teams, improve the code, and decouple the qualities of subdomains.

<ins>Prerequisite</ins>: there is a natural way to split the business logic into loosely coupled subdomains, and the subdomain boundaries are sure to never change in the future.

Splitting a Monolith into Services by subdomain is risky in the early stages of a project while the domain understanding is evolving (in-process modules are less risky but provide fewer benefits). However, this is the way to go as soon as the codebase becomes unwieldy due to its size.

<ins>Pros</ins>:

<ins>Cons</ins>:

Add or split a service

A service is split from a monolith.

<ins>Patterns</ins>: Services.

<ins>Goal</ins>: stop digging, get some work for novices who don’t know the entire project.

<ins>Prerequisite</ins>: the new functionality you are adding or the part you are splitting is weakly coupled to the bulk of the existing Monolith.

If your Monolith is already hard to manage, but a new functionality is needed, you can try dedicating a separate service to the new feature(s). This way the Monolith does not become larger – it is even possible that you will move a part of its code to the newly established service.

If you are not adding a new feature but need to change an old one – use the chance to make the existing Monolith smaller by first separating the functionality which you are going to change from its bulk. At the very minimum this two-step process lowers the probability of breaking something unrelated to the required changes of behavior.

<ins>Pros</ins>:

<ins>Cons</ins>:

<ins>Further steps</ins>:

Divide into a Pipeline

A Monolith is transformed into a pipeline.

<ins>Patterns</ins>: Pipeline (Services).

<ins>Goal</ins>: decrease the complexity of the code, make it easy to experiment with the steps of data processing, and distribute the task over multiple CPU cores, processors, or computers.

<ins>Prerequisite</ins>: the domain can be represented as a sequence of coarse-grained data processing steps.

If you can treat your application as a chain of independent steps that transform the input data, you can rely on the OS to schedule them, and you can also dedicate a development team to each of the steps. This is the default solution for a system that processes a stream of a single type of data (video, audio, or measurements). It has excellent flexibility.

<ins>Pros</ins>:

<ins>Cons</ins>:

Further steps

As your knowledge of the domain and your business requirements change, you may need to move some functionality between the services to keep them loosely coupled. Sometimes you have to merge two or three services together. So it goes.

Systems of Services or Pipelines are quite often extended with special kinds of layers:

Diagrams of Services with a proxy, Services with an orchestrator, Services with a middleware, and Services with a shared database.

Each service, being a smaller Monolith, may evolve on its own. Most of the evolutions of Monolith are applicable. The most common examples include:

Diagrams of a scaled service, layered service, Cell, and a service that implements Hexagonal Architecture.

External links