Nowadays, Monolithic Architecture carries this exaggerated ill fame. I personally worked with a few monolithic architectures in the past. And there’s something shameful in admitting that you work or have been working with a monolith. Imagine going to the interview and saying that you have deliberately built a monolith… Without supervising this claim with a context, you probably better not wait for an offer.
Surprisingly, as we’ll reveal a bit later, such a bad reputation was not caused by an architecture itself, or should I say solely by it.
So why does this revolting feeling occur every time someone mentions Monolithic Architecture? And why do organizations keep building monoliths nowadays?
What is a Monolith?
I’d like to draw a bold line 🖍️ between monolithic architecture and a big ball of mud.
The Monolithic Architecture suggests that the application is a single unit, single logical executable, and single whole. Thus application is stored, developed, built, executed, and deployed as a single unit. The Monolithic Architecture is self-contained application architecture.
Monolithic Architecture itself does not suggest any specific implementation practices or patterns. Underneath it might have a good separation of concerns (SoC), follow SOLID principles or implement event-sourcing, built within functional or object-oriented paradigm, etc.
I’d like to emphasize that the Monolithic Architecture is not a bad practice or an anti-pattern. As well as the monolithic application is not necessarily a poorly designed one, and internally employs the worst available practices.
So what’s the catch? 🤨
Any organization that designs a system will produce a design whose structure is a copy of the organization’s communication structure.
— Melvin E. Conway
An application and thus an architecture is a permanently evolving organism. It changes and adapts to an ever-changing environment. To survive it has to react to the most critical factors of the environment. Those factors usually include (but are not limited to) business needs and/or market opportunities, technical limitations and scalability requirements, financial aspects, etc. Therefore any architectural decision must be always viewed in the context of the time, phase of the product, and business targets at the time.
Most of the time Monolithic Architecture is an unavoidable first step in the solution lifetime and the first stage of the application architecture evolution. And there are a few good reasons for that. First and foremost it is the easiest and fastest way to build an MVP (minimum viable product). Whereas time is an essential factor, especially if an organization adopts Lean Design and Agile practices.
Often MVP is produced by a rather small organization or unit within the organization. Where communication between all members is efficient and effective. Given all that, this design fits well with Conway’s law.
Pivotal point 📉
Of course, Monolithic Architecture has its own limitations (we will look closely on them in a few moments).
And the first time when business bumps into them, it is rather a good sign. It signifies that the business took advantage of the market opportunity and successfully passed early adopters' validation. This is a pivotal point.
It is crucial to recognize achieved milestones. And gently start shifting from strategic to tactical thinking. With business moving into the transition phase, it is a perfect moment for architecture limitations assessment and its re-consideration.
Neglecting architecture evolution will unavoidably trigger fast-paced technical debt accumulation. And the dark side of Monolithic Architecture will start to show off. A rapidly growing business will most likely observe a snowball effect vividly, where overall development efficiency and application availability will degrade exponentially with respect to the business growth.
All limitations we discuss below become evident after the MVP milestone. Where application enters the rapid growth phase. Focus transitions from the validation to the market growth (increase in active users) and new feature development become the main focus. This usually comes hand in hand with the development forces count increase.
However, the longer the application architecture stays unchanged after the MVP the more emerging effect these limitations will have.
This is where the bad reputation for Monolithic Architecture is originating from.
The Monolithic Architecture suggests a single shared code base. And a single source of truth for the application’s data.
A growing amount of contributors will increase the effort required for new feature development. At first any significant and later almost any change will require a series of meetings between teams and extra orchestration.
Obviously, it will unavoidably increase development time. And as a side-effect, it will also build up developers' reluctance to change shared parts of the application, especially the data-access layer. Which will lead to mixed separation of concerns (SoC) and ultimately degrade code quality.
The growing amount of contributors and teams entails a growing amount of integration/friction points. Any small change requires the re-deployment of the whole application. Deployments and especially releases now feel like a burden
Continuous Deployment quickly goes out of the question.
The release process becomes convoluted, shattered with bottlenecks and various box-ticking exercises.
Every release will require some involvement from at least one representative from each team. Release of any size must be planned in advance. Often organizations introduce gatekeepers to control the process.
Often each team will have its own dedicated testing environment to ensure that the development and feature testing process is isolated from constant interruptions by other teams' changes. This in its turn will introduce a certain level of testing redundancy in the release process, as now changes must be double-checked in the scope of release changes.
Monolithic solutions have only one way of meeting growing demands. Scaling up, aka vertical scaling strategy. In other words, grow machine resources. This approach has multiple well-known disadvantages compared to scaling out (horizontal scaling strategy). And typically considered as a poor choice for scaling strategy.
Compared to scaling out. It has a close hard limit. It is not flexible and poorly handling spike loads. Finally, it has lower failure tolerance and unavoidably longer downtimes. Should I say it is way more expensive?
Monolithic Architecture is usually constrained by technologies selected in the early stages.
However, things are not necessarily smooth even with the existing tech stack. Any change in the framework or language will impact the whole application.
Version upgrades are a risky and laborious process. Usually postponed for as long as possible. And as you can guess only stimulates technical debt accumulation.
As an alternative to the Monolithic Architecture community came up with a Microservice Architecture (aka Microservices). However, often developers unintentionally introduce Distributed Monolith instead of (or within) Microservice Architecture.
A common delusion is that a Microservice Architecture is an approach where some business process or application is built from a set of services (preferably small) as opposed to a Monolithic Architecture where everything is self-contained in a single whole.
This is somewhat true. Although the definition above is leaking a few critical details.
A Microservice Architecture is an approach where the application is built with a set of independently deployable services. The separation of concerns (SoC) is used to decide what concludes an individual service. Hence each service has its own business flow, well-defined purpose and boundaries. Each service is either stateless or owns its data.
The Distributed Monolith is an application that does satisfy the first definition but does not satisfy the second one. Or…
A Distributed Monolith is an approach where the application is built with a set of services and at least one of the points below is true:
- some services can’t be deployed independently
- some services are very chatty
- some services share data source
- some services don’t scale dynamically (independent scaling)
Nowadays Monolithic Architecture is still a good tactical architecture for building an MVP. However, it is very risky to follow a monolithic approach after the initial phases of the product.
Amazon, Netflix, and many others started with Monolithic Architecture. Of course, at that time they didn’t have much choice as Monolithic Architecture was considered a traditional architecture, there were no cloud providers, etc.
Nevertheless, nowadays a lot of organizations prefer to start with a Monolithic Architecture. Some of them wisely left the door open for further architectural evolutions. And more importantly, use it when the time comes. Others don’t and as a result their development process ends up in a stagnation and solution falls into the tech debt spiral.
In the latter case ultimately everyone agrees to blame Monolithic Architecture and promise “never again”.
I think Monolithic Architecture is undeservingly carries bad reputation. Even nowadays Monolithic Architecture has its own place and purpose in business automation and application development.