DEV Community

Marcus Rådell
Marcus Rådell

Posted on

"One size fits all"-services

Most new projects seem to make an important architectural choice between deploying a microservice architecture or monolith. I will make the case that you should always follow some basic rules of microservices, and start with a monolith. I will call this setup "modular monolith".

Let's start to define a typical monolith before jumping into a modular monolith.

Layered architecture

A typical layered architecture will have global layers where the controllers have access to all the models which are in the layer below controllers.

Access to everything is pretty much the definition of the ball-of-mud architecture. Luckily, the layered architecture does reduce vertical access for any layer to only one additional layer below.

Monolith

When we change a small thing, we still deploy everything. And that deployment will be a single artifact.

If that is a good or bad thing will depend on your needs. In general, each infrastructure artifact involves some added complexity, so we want to keep the number of services deployed to a minimum. Monoliths is optimized for low complexity in your infrastructure.

Microservice

At a high level a microservice encapsulates its database schema (a set of database tables). Nobody outside of the service is allowed to query the database tables that belong.

Internally, it might not use layered architecture because the amount of code is less than in a monolith. Code architecture becomes optional as long as the amount of code stays small.

When a microservice is deployed, it is done so without affecting other services in the system. You can independently scale up a microservice's resources to handle more load. Microservices gives us more control over the infrastructure which we pay for in an increase in complexity.

Modular Monolith

If we imagine that we took a bunch of microservices, and merged them into a single server, that would give us a modular monolith.

Each service in our server would own its database schema, and to communicate between services, we always go through the service API. That usually means calling a method on an object and not doing a http call.

The overhead of managing each service is as small as in a traditional monolith. The encapsulation the same as in a microservice. As a bonus, you can move code around and change your service boundaries pretty fast. This makes the system simpler to change. Once the service boundaries are stable, you can try to promote a service into a microservice.

The main downside is that there is little documentation on how to write a modular monolith, and the team might drift towards a ball-of-mud layered architecture where they allow all services to query everything in the database. Having the mindset that you are doing microservices, but with one deployment, can help.

Top comments (0)