What’s the Difference Between Monolith and Microservices?

Posted in

In the world of programming, there are few terms as discussed (and misunderstood) as monoliths and microservices. Often positioned as a competing precedent and antecedent, the relationship between the two concepts is more complicated than meets the eye.

Today, we’re going to define what monoliths and microservices are. We’ll also look at some advantages and disadvantages of both, as well as discuss the current trend of enterprise movement into microservices from the perspective of codebase complexity.

What’s a Monolith?

The monolith is considered a “classic method” of service development. The paradigm itself is a holdover from the era of mainframes and clients, where individual interfaces relied on a single, distant packaged application on a mainframe. This mainframe was overwhelmingly powerful compared to the relatively threadbare systems of that time. With such a single, powerful system on the network serving multiple clients, it only made sense to develop in a vertical stack.

Monoliths are best thought of as a non-distributed solution. In this design paradigm, everything exists in one body, with the databases, the application, and the interface occupying a dependent position. The user interface, business logic, data supports, and applications all exist as a single entity within the greater network. In practice, this essentially means that a monolith is a self-contained entity, a giant structure with everything in linear build.

The problem with the monolith approach, however, is that nothing is truly modular. From the very beginning, the goal was to develop a purpose-built service to provide a function. There was little consideration given to the idea of breaking these components into individual, reusable pieces. The main negative caveat is that the monolith comes with increased difficulties as the problem complexity and computational powers increase. At a certain point, the monolith can grow too large and unwieldy.

Further, having a single machine do what many distributed machines can do (and arguably better) becomes wasteful in an era of high-powered small computation devices. However, there are some positives to the monolith approach, which is why it still holds sway in development circles.

What’s a Microservice?

The microservice architecture was envisioned in part to solve the underlying issues of a centralized monolith approach. Simply put, microservices are distributed. A core problem underlying the monolith approach is that everything is centralized, and as such, the choice to adopt microservices is essentially an opposite path. Microservices are a collection of small services, each developed as its own segment as part of a collective group of services. A microservice may be self-contained, but it typically functions as one of many services that make up the overall core process.

One way to think about microservices architecture is to imagine an organism. Every part of the microservice collection is an eye, a finger, an ear – all of these specialized organs work in concert with one another. While it’s true that an eye can carry out its function independently of the rest of the body, it is best leveraged with other aspects of the larger organism.

For a more real-world analogy, imagine a hotel’s software environment. If the hotel were using a monolithic codebase, everything would exist in a single siloed system. The reservation system, the database of current customers, entertainment delivery, room service – everything would depend on a single, centralized system, and a single interface. This would add incredible amounts of complexity – imagine being the single developer responsible for that entire codebase!

In a microservices environment, however, everything is broken into smaller segments. While the end-user may still use a single interface, their requests are routed to the appropriate microservice depending upon the nature of their application and the resulting output. Individual parts of that system can be changed, reused, iterated upon, even replaced, without affecting the total environment. APIs are leveraged for communication to allow this decoupling to occur, and each microservice represents a defined scope with a specific function.

Monolith Advantages

The most significant advantage of the monolith is that it creates direct control over every aspect of the service. When everything is a single silo, there are no variations. What is done to the service is done to the service in a one-to-one relationship. This simplifies development (at least at the start), as the only thing that needs to be coded and developed is the singular relationship between the components of the service and their external interface.

Additionally, this makes deployment rather easy as long as the deployable is small. The service is one entity, and as such, a change that affects the entire service can rather easily be deployed. With a monolith, horizontal scaling is technically feasible and comes down to “throwing more resources at the service.”

Having total control over every aspect of a service in a singular, packaged form is a key reason why monoliths still exist. Monoliths tend to occupy scenarios where distributed microservices are too complex or too broad an exposure. For this reason, monoliths are more common amongst high-security enterprise users.

Monolith Disadvantages

Unfortunately, depending on the use case, the monolith may have far more disadvantages than advantages. Simplified deployment and development are valid when the codebase remains lightweight, but as complexity increases, so does the difficulty in both management and iteration. As the monolith grows, it quickly becomes too top-heavy, requiring more resources and effort to manage the core functionality.

As a result, scalability suffers as complexity grows. Scaling a monolith is basically “throw more resources at the problem and load balance the result,” but this has diminishing returns. More to the point, there are only so many resources that can be thrown at a problem. In a monolith, the business logic is reflected in terms of complexity. With each increase in data volume, this complexity compounds even further.

With a monolith, changes to the codebase (either in terms of management or iteration) typically mean a massive deployment across the entire monolith. If developers don’t abstract code into smaller parts, a singular update must affect every point of the larger strata. Massive unified deployments can easily hurt agility and cause slower releases.

Monoliths can also be challenging to maintain. When a bug affects a single aspect of a monolithic codebase, it affects everything. Where an offline microservice may only affect one or two applications, a monolith could mean widespread downtime. Small bugs could have a disproportionately large impact, and testing to mitigate these bugs becomes a burden.

Microservice Advantages

The primary benefit of a microservice approach is that the cost for deployment, development, and iteration is significantly reduced over time. Deploying elements in pieces rather than as one whole brings many practical positive effects.

First off, microservices isolate bugs. Since services are segmented by design, bugs will only affect a single part of the codebase. Thus, they are easier to fix. In general, microservices enable more granular control. Each microservice can be controlled as a single entity, allowing for quicker repairs, iterations, and updates.

While complexity is indeed increased due to the nature of having many independent parts, the complexity of coding a singular aspect is often reduced. Given that the coding process is independent (or decoupled entirely) from the broader microservice ecosystem outside of simple hooks or endpoints, individual interactions are far more straightforward. While the additional layers necessary to enable microservice functionality do add complexity, they can often be simpler than the requirements inherent in developing the monolith itself.

Another significant benefit of microservices is improved extensibility. Imagine having to replace a set of wrenches every time you needed to replace just one – that is akin to the monolithic experience. In microservices, if your 10mm wrench is broken, you can just replace that single wrench. This is also true for replacing technologies in the microservice realm. Whereas monoliths are typically tied into a single technology framework, microservices can host a wide array of technologies or languages within an ecosystem. This allows for more natural innovation, rapid prototyping, and quicker pivots in business logic.

Microservice Disadvantages

Microservices are not without their disadvantages, however. Given that these caveats are often under-considered when framed against the monolith, they bear specific consideration.

Microservices add networking complexity. With microservices, you must figure out how each service ties into each other at the macro level. While individual unit development is much simpler, the overall system does become more complex.

Whether or not this complexity is equal to, less than, or even higher than the monolith requires an investigation of your current situation. Adopting microservices for a single-use, single-deployment application, for example, could easily be more complicated and would warrant a monolithic approach instead. It all comes down to the project scope. Microservices will generally be less complicated at the micro-level, yet and equally sophisticated on the whole.

What about changes that affect an entire system? A monolith can be updated as a whole because everything is tied together inexorably. However, since a microservice architecture is distributed, updates across the entire system (such as adopting a new version of a chosen language or protocol) can be more expensive. You’re updating both the microservice itself and the interconnected parts that make it all work. Solving these issues at an enterprise scale will likely require a management layer. Containerization and service mesh, for example, are enabling both distributed environments and a unified control plane.

Will Enterprise Development Trends Replace the Monolith Paradigm?

We tend to view monolithic development as a precursor to microservices. However, this is not entirely accurate. The monolith does have a reason for existing, and in many cases, is still an appropriate solution. The monolith became popular for a reason – its requirements were small to start, and its performance was often excellent due to the nature of singular demand on memory and processing.

While the monolith has become less popular due to the difficulties of deployment and iteration, there are still many use cases where this is an appropriate approach to take. Yes, a monolith is essentially tightly coupled. But, when an application is meant for a single purpose and has to be coupled, this is not a negative.

There is still value in constructing a monolith. For that reason, it is better to consider the relationship between monoliths and microservices akin to API design styles. SOAP, REST, gRPC, and GraphQL are different approaches for different purposes. As we’ve defined before, all these styles can work well in their given circumstances. In the same way, even as many enterprise users have moved from the monolith to the microservice collection, it’s not correct to say that one is better than the other.

Conclusion

Monoliths and microservices have their place in the greater design ethos of APIs and are each appropriate for particular purposes. While the monolith delivers some simplicity and ease of development in the micro, the macro often benefits from a movement to microservices. The size of the application and the constituent elements changes the benefits derived from either solution. Thus, project scope bears ardent consideration when judging the two options for any codebase.

What do you think about monoliths? Do they still have a place in modern development, or are they a relic of a bygone era? Let us know in the comments below!