Imaginary 🔥 Inpho

Monolithic vs Microservices Architecture: An Overview in Plain Language

I recently wrote about this topic as a report for my work. We were looking ahead to rebuilding our company's internal software application and a consultant we'd hired had recommended the microservices architecture.

But I wanted to do a deeper investigation into the pros and cons to get a better understanding of whether or not it made sense for us.

I'm thankful I did because, judging from what I found, going with microservices would have caused us a lot of pain.

Monolithic Backend

A monolith is a unified backend architecture where all modules, functions, and services are bundled and deployed together as part of a single codebase. Typically it is connected with a unified (ie. monolithic) database as well.

Advantages
Disadvantages

Microservices

With microservices the application is broken down into its component parts and a completely independent microservice is built for each one, each typically with its own individual database as well (but not necessarily). An API Gateway is then built to make requests to each of the services. The frontend client makes all its requests to the Gateway, not to any of the microservices directly.

It is extremely crucial when using a microservices architecture that each module/service is separate so that each one can be dealt with independently of the others. Or else all you get is the added complexity and none of the benefits.

Advantages
Disadvantages

Key Considerations / Questions

The danger of creating a distributed monolith.

Microservices only work if each microservice is completely independent. This requires a very careful design and detailed understanding of the system's modules and the actions they’re performing.

If the microservices become closely coupled with each other (one module sharing dependencies with another), you get a distributed monolith, which is the worst of both worlds. It means all the complexity of maintaining multiple microservices with none of the benefits.

Modular Monolith?

A modular monolith is a kind of compromise between microservices and a monolith. You build the app as a monolith, but you pay close attention to keeping the different modules separate and independent (this is good practice regardless).

This method retains the simplicity of the monolith, while still remaining flexible enough to slowly transition to microservices if/when the need for it becomes more pronounced.

Analysis

The companies that migrated to microservices tend to be very large (Netflix, Atlassian, Twitter, etc.). They have multiple teams of developers working on various parts of the application. Microservices are useful for them because the benefits at that scale are worth it for the extra complexity.

Most companies are not as big by comparison and that should prompt you to question whether microservices would be a good idea for your situation. As with anything else, it has benefits, but they’re not free.

Scaling

Being able to scale modules up individually can be nice, but there are often lots of opportunities to address performance in ways that don’t require a wholesale change in architecture. For example, using some insights from DataDog had a dramatic impact on performance for us in a very small amount of time and with very little cost.

It's a good idea to look for other opportunities like this that can make a big difference and cost much less.

Fault Tolerance

Being able to isolate issues to individual modules so that they don’t bring down the entire app can be nice, too. However, having good test coverage can help a lot more in terms of helping you identify where a problem is and how to fix it. It will also help prevent a lot of problems in that you can quickly verify that you're not breaking something before deploying new updates to the code.

Testing is also something you usually have to do regardless, and having a unified test suite in a monolithic app will be much easier to deal with than managing multiple different test suites across multiple different microservices.

Deployment

Deployments for a monolith are simpler than having to manage multiple different deployment pipelines for all of your different microservices. And if you do get a bug that crashes the system, having a simpler deployment process can help you get the fix out faster.

There's also the issue of how you'll be setting up the repos on GitHub. (You can check out this video for an overview of that whole problem.)

It may be that once you have the microservices deployment system set up, deploying to a single microservice could be simpler. But keep in mind that doing the work of setting up that microservices deployment system will likely be pretty complicated.

The Distributed Monolith

The danger of your microservices inadvertently turning into a distributed monolith is very real. Tight coupling across different modules can happen very easily if you're not careful. And it's not always obvious to figure out where one service ends and another begins.

If you commit to microservices from the start and come across this problem, you're stuck.

The Modular Monolith

Building an app as a modular monolith is something you should consider before diving into a microservices architecture. It lets you keep the simplicity of the monolith and gives you the flexibility to transition to microservices down the road.

And if you do decide to transition to microservices, you now have the option to do it more gradually, extracting out one module into a microservice and seeing how that goes. As opposed to having to manage 20 different microservices off the jump.

#blog