A good software architecture is a combination of science and art. It is really hard to get it just right, and once you’ve implemented your system, it is often hard to perform big architectural changes to it. i.e. it will cost you $$$!
There are a lot of factors you need to consider before designing an Architecture for your system, some of which are technical constraints. For example, today with the power of the Cloud, it is way easier to implement distributed systems that scales on demand, than it was about 10 years ago, and systems that were designed at that time, had to take it under consideration.
Even though good Software Architecture principles will always be true, some techniques and choices that are decided upon due to technical constraints, may become obsolete once those technical constraints are expired.
Monolith is the new scary term in Software Architecture. It is often used as an insult by advocates of current trends which are strongly in favor of Microservice-based architecture.
What is a Monolith?
A Monolith system can be considered as an architectural style or design, in which all functional aspects and modules of a system are intertwined together as a single and self-contained unit, often as a single process in a single machine.
Such systems were historically common when working with (or even considered a byproduct of) traditional software design processes like Waterfall, that pushes for big teams with less focus on iterations, and more on launching a product with as much features as possible.
Are Monoliths that bad?
While Monoliths have advantages like being:
- Simple to deploy as a single unit – There aren’t a lot of moving parts, sometimes it is enough to copy the files to a server.
- Simple to perform End-to-End testing – Testing is done against a single application.
- Easier to debug – It is usually easier to debug a single and self-contained system over a distributed system.
- Easier to implement – It easier to implement new projects as Monoliths over Microservice-based system for example.
They violate two important principals of Software Architecture: High Cohesion and Low Coupling.
Cohesion is a measure of the degree to which a module performs one and only one function. Coupling is the degree of how closely modules relies and connected to each other.
We usually aspire for high cohesion and low coupling. Due to its nature, a Monolith tend to be less cohesive and by result tightly coupled.
Tight coupling and low cohesion have several implications. Software with Tight coupling and low cohesion tend to be:
- Hard to modify – a change in one module usually forces changes in other modules.
- Harder to reuse and test – Certain modules might be harder to reuse or test since dependent modules must be included.
- Hard to scale – It could be challenging to scale a single module in a Monolith without the need to scale the rest of the dependent modules, even when there isn’t a need to (Scale up).
- Limits the dev stack – dependent components often have to use the same technology.
- The DevOps process is hard.
- Hard to understand – hard for a single developer or a small team to understand the entirety of the system.
- Hard to update – can’t update a single part of it. You will have to update the system as a whole.
- Less reliable – bug in a single module, like a memory leak might break down the entire system.
In addition, the Architecture you use for your system doesn’t just impact the system’s structure; more often than not it has implications over aspects like deployment speed, team sizes and organization and project management. Tightly coupled systems tends to lead to bigger teams, slowest shipping time and to less agility.
That being said, selecting a Monolithic architecture isn’t always a bad choice. There are situations, where a Monolithic architecture might be a good choice for you. For instance, when building POC’s or projects that are either small or will shortly live.
What is the alternative?
If a Monolithic Architecture is on one side of the spectrum, being Highly coupled and with Low Cohesion, on the other side of the spectrum there are Microservice-based Architectures.
What is a Microservice-based architecture?
In essence, A Microservice Architecture is a method of dividing and building software as small, lightweight, distinctive, independent and message-enabled modules that are independently deployable.
Instead of building a single service or process that responsible for all of the functionality, with Microservice-based architecture, you divide the functionality into small services that are usually distributed and decoupled from each other.
Are Microservices that good?
Microservice-based architectures have advantage like being:
- Simple to deploy each service – each module can be deployed independently and gradually without impacting the rest of the system.
- Simple to scale – each module can be scaled on demand accordingly without affecting the rest of the system.
- Simple to reuse and test – each module can be tested or reused independently.
- Simple to update – it is easy to update modules as independent units.
- Easy to modify – a modification to one module shouldn’t force changes to other modules.
- Having flexible dev stack – each module can possibly be developed independently with different frameworks, programming languages and technology.
When working with Microservice-based architecture it is common to have small teams working independently on different modules. This could be a big advantage, since each team can utilize their own particular set of skills using technologies of their choosing, without forcing other teams to use them as well.
In addition, since current trends are in favor of Microservices, a lot of the frameworks and cloud technologies being developed today have Microservices in mind. This means there are a lot of tools and frameworks that you can utilize while building your system, such as the power of the cloud.
Where is the catch?
Everything comes with a cost. It is usually hard to develop a Microservice-based architecture.
- It is much harder to deploy at first.
- Much harder to debug a distributed system.
- Serialization, Deserialization and round trips of messages impacts performance.
- Much harder to configure.
- Much harder to monitor.
- Much harder to orchestrate and manage a sizable amount of distributed services.
- Adds complexity – more moving parts.
In contrast to Monoliths, configuring and monitoring a lot (might be tens or hundreds) of distributed services is a challenging task. There are tools and frameworks that are designed for this purpose, like Containers for hosting services and Kubernetes or Azure Service Fabric for monitoring, configuring, orchestrating and automating them.
As a result, when working with Microservices, a sizable portion of the effort is invested into DevOps and into working correctly with orchestration tools. If you are not aware of that, it could cost you.
These tools are usually a blessing and a curse. They do a great job, but since the task is complicated, so are the tools. They are additional technologies and tools that developers must learn and understand before they can productively work on your system.
Designing an Architecture for a system is hard. There are a lot of factors to consider and it needs both a touch of science and a touch of art.
A Monolithic Architecture isn’t popular these days and for good reasons. It is Highly coupled and have low cohesion, with all of the implications. That being said, there are still use cases where you should prefer a Monolithic architecture for your system.
Current trends tend to favor Microservice-based Architectures, and current cloud technologies are best utilized with Microservices. A Microservice-based architecture tend to be loosely coupled and have high cohesion, making it simpler to update, modify, test and scale, which in return requires a lot of configuration, monitoring and orchestration, a task that is not that simple and requires a specific set of skills. Orchestration tools are a big part of a Microservice-based architecture.
It doesn’t matter on which side you are closer to in the Architecture spectrum mentioned above. Choose the Architecture that suites your needs. With Monoliths on one side and Microservices on the other side, your best choice might be somewhere in the middle.