The monolith is an architectural pattern where the software application consists of a single executable that is deployed as a whole. It can be difficult to work with when it is being maintained by a single team. But matters worsen if it is managed by multiple teams. Here’s why.
How Monoliths Grow
When a company starts a software product, it usually is a single application. Especially when things need to move fast and there isn’t a lot of time for architectural concerns. That doesn’t have to be a problem. The application is small and can be supported by a small team.
But over time, the application grows in size and in features. Technical debt increases as code is added without taking the time to refactor and improve the architecture and code quality. After several years, you end up with what developers resentfully call a monolith.
The term has a negative meaning to many developers because for them it is synonymous for a mess of code they can no longer easily navigate through. It’s often untested which means the bigger the change, the bigger the chances of regression bugs are. The team will only make minimal changes, further exacerbating the situation.
As the system grows, it can no longer be maintained by a single team of a handful of developers. So extra teams are formed. They each try to take on a part of the monolith. In the past this was often along technical boundaries: a UI-team, a backend-team, a database-team, etc. You still see this, but many companies also split along functional boundaries: a user management team, an order processing team, a stock keeping team, a billing team, etc.
So you still have a monolith, but it’s now a multiteam monolith. Is this a good or a bad situation? It can be a first step towards multiple independent services maintained by their own teams. But it’s definitely not ideal and will often increase the problems you already had with the monolith.
The Issue With Multiteam Monoliths
Here are several problems I see with multiteam monoliths.
A first problem that multiteam monoliths cause is the issue of ownership. With large monoliths it may not always be clear who owns which code module. If it isn’t clear who is responsible for a certain module, its quality can deteriorate in several ways:
- teams change the code without implementing tests
- the module doesn’t get important security updates
- nobody removes the module when it is no longer needed
- there is no team to provide support to other teams (answering questions, updating documentation)
- it is unclear who should fix bugs
In case the ownership is clear, it may not be clear what ownership means exactly. Can other teams make changes to the code of a module owned by another team? They have access to the source code repository, so what’s stopping them?
The company may have agreed that teams should ask the owning teams for any changes. But those developers may be swamped in work and just tell the requesting team to go ahead and make their changes. Which puts you back in the original situation of a multiteam monolith with no clear ownership.
Multiteam monoliths often also suffer from a multitude of coding styles. Different teams have different ways of programming. They are more or less familiar with certain patterns than other teams. They each try to solve the problems at hand in their own specific way.
And that’s fine. If you’re working with separate services (microservices if you want), each team can apply their style in isolation. If it’s a multiteam monolith, it will have a mix of styles and you end up with an inconsistent codebase. This increases the mental load for developers when navigating the code. In some cases, this can produce the lava layer (or flow) anti-pattern.
The Real Solution
Getting out of this situation can be tricky and a multi-year effort.
If there is an overarching team (an architecture team often), they can facilitate in the effort as they can take or give ownership. A first step is to remove any modules no longer used. Then, everything depends on priorities and estimated effort. But here are some steps that the company should take:
- Give specific teams ownership of specific modules
- Split modules into their own repositories and release them as libraries to be used in the monolith (combine with the previous step)
- Split of entire functionalities into separate services/applications and assign them to a single team
- Educate teams about what ownership means (not just code but also testing, releasing, documentation and support)
Move Away From Your Multiteam Monolith
The multiteam monolith is a specific form of the monolith application. It’s a concept that encapsulates both an architectural pattern and an organizational practice. The multiteam monolith is a hard pattern to uphold and leads to low quality code and frustration among developers. It isn’t easy to solve and it takes time, but it’s definitely not impossible. Start with small steps to get the ball rolling!