Let's first discuss what a monolith is. In software development, a monolith is thought of as a single application, service, or class that has many responsibilities. In reference to backend services, it generally refers to a single large service that manages all the domain responsibilities needed for the team or organization. This type of service may often be the result of an early prototype or implementation that has grown over time, responding to an ever-expanding list of business requirements. This often leads to functionality being bolted on, small hacks being applied here and there, and a general increase in complexity for the entire system.
This accumulation of complexity, patchwork features, and technical debt may weigh heavily on the system over time, and can start to have a genuine business impact for a team or organization. Monolithic services tend to be very interconnected as they handle many different responsibilities. It may be difficult to understand where to make a change when adding a new feature, and it may be unclear how that change may impact the system as a whole. This leads to increased maintenance costs. If it's more difficult and time-consuming to improve the system, two things may happen:
- Any critical bug fixes or improvements will inherently require more time, energy, and money.
- As these costs increase, the fixes may be deemed less and less critical and, therefore, the quality of the system may begin to decrease even further.
The interdependencies in a monolithic system make it difficult to monitor, trace, and debug issues within the application. How can you isolate a single data flow? How do you measure performance of a single aspect of the system? These types of questions may become impossible to answer.
Because monolithic applications are more challenging to monitor and debug, it becomes equally as difficult to truly understand the performance characteristics of the system. This opens the door for inefficiency both in the code, and in the deployment hardware used to host the system. If we can't become more performant through code improvement, the next best option is to throw more hardware and money at the system in the hope of masking performance issues with faster machines. While this may work for a time, it likely isn't the best way to scale your services in the long run.
Over the years, these are the challenges in maintaining and scaling applications that have lead organizations to explore and adopt microservices architectures.
In the next section, we'll discuss what microservices are and how they aim to improve on monolithic systems.