Monolithic or Microservices? The Question You Shouldn’t Really Ask Yourself
Monolithic software architecture has been here for a while, while microservices represent a fairly modern approach to app-building, used by worldwide giants such as Twitter, Uber, Spotify, or Netflix, so it seems it’s here to stay.
But what’s all the fuss about? In this article we will:
- Familiarize you with the concept of monolith vs microservices approaches
- Show their main pros and cons
- Present the microservices architecture in the context of the Jamstack approach
- Tell you how to migrate from a monolith to microservices
- Advise on which to choose for your project
Let’s take a look!
Monolithic vs microservices: what’s the difference?
Monolithic architecture of a piece of software – as its name accurately tells us – wherein all the functions of the entire application are put together in one codebase.
A monolithic application is a large block of code with multiple modules, tightly coupled together as a single instance. Its architecture is three-tiered, and consists of a database, a user interface, and a server-side application.
This has many implications which we will discuss later.
Microservices architecture, on the other hand, means that all the functions and business capabilities of a microservice application are broken down into separate modules that are called microservices – each of them has its own database (there are multiple databases) and communicates with others through API and HTTP protocols.
Each microservice can be hosted and developed as independent services, and this type of architecture is also technology-agnostic, so it offers more flexibility for developers.
Microservices are specialized – each of them is focused on just a single function, and because of that, each is more efficient than a monolithic system.
Microservices vs monolith plugins
It’s vital to add that we can extend the monolithic architecture (such as WordPress) with add-ons and plugins that may imitate the microservices’ functionality to some extent.
It isn’t, however, a perfect solution, because it may lead to mistakes:
- Not all the plugins cooperate together well
- An overloaded website may load slowly or result in 429 error
- Plugins may lose the support of their creators (which is a common problem in the open-source world)
Microservices architecture pattern is much more than just a collection of plugins or functions: it’s a whole logical system, where none of the functionalities are redundant or duplicated. We will explain it in more detail when talking about migration from monolith to microservices.
Monolith, microservice and Jamstack
Microservices are a part of the broader Jamstack approach. We have discussed this idea in many of our blog posts, sometimes directly, and sometimes in the context of other subjects, so we will just briefly recall the idea here.
It is possible because, in Jamstack, the front-end layer is decoupled from the back-end layer, and you may be able to use the same back end with many different front ends.
Like microservices, Jamstack is the opposite of the monolithic approach.
Microservices are thus a subset of the Jamstack approach – all the tools like payment services or chats are, thanks to using API, brought directly to the front end, and not to the back end of an app or a website.
Having said that, let’s come back to monolith vs microservices, taking a look at their pros and cons.
This method of development is historically typical, and it still holds some pros – later in the article we will discuss use cases that take those advantages into account.
The main advantage that can be described by one word, is simplicity. It allows for peace of mind, because you just have one app to build, monitor, use, and test.
You also skip lots of operational duties, like interservice communication or decentralized data management.
The deployment process is also simpler because it involves just one file as a result, and the development is usually streamlined and standardized.
What’s also important is that monolithic services are efficient by nature – latency is rarely an issue, and centralization leads to good performance. Unless you need some additional features – they can slow down a website noticeably.
Monolithic architecture comes, on the other hand, with many disadvantages. But if it didn’t, we wouldn’t have to come up with the microservices idea in the first place.
First of all there is the issue of low flexibility and scalability – you are sentenced for a long time to the same technology stack, and the adoption of new solutions or third-party tools is highly problematic.
As the codebase grows, it is more and more difficult to operate the system, because one small change could make it collapse, and the maintenance is also tricky.
Updating one piece of code may break dependencies in other areas, and intertwined data relationships make it all look like an impassable thicket.
This has also another aspect – it is difficult to build a monolithic app, because you have to prepare and test everything in one go. Needless to say, one small bug may bring down an entire application.
The microservices architecture allows to solve all the above problems.
It is highly scalable and flexible; you can easily scale both individual components and the whole application without affecting the codebase.
The modules may be developed and updated independently of each other so you can update just a single function, not the whole system, and the latter won’t entirely break down because of one single problem.
It is possible to use many different technologies and programming languages, because microservices are tech-agnostic.
It’s also vital to add that microservices development is easier to organize and manage – you have a bunch of small cross-functional teams instead of one big team, which allows for easier communication and simplification of processes.
There are, however, some cons involved.
First, scaling the app may bring many concerns about the proper structuring of the components, which will be discussed later while talking about the migration from monolith to microservices.
The complexity also makes the app more difficult to test, because you have to test not only individual services, but also their interactions in various business flows.
Finally, an application based on microservices architecture can also bring about minor security challenges, as there is a lot of information continuously exchanged between the modules.
What should you consider while switching to microservice architecture?
This is a very important choice that will influence the whole lifecycle of your application and affect its maintenance throughout. You should take into account several factors, such as:
- The nature of the application – we will provide you with a list of use cases later in the article
- Business risk – although microservices architecture has many advantages, choosing it may require more work at the beginning because it’s a totally new approach that will likely require some changes to existing business logic and processes
- Infrastructure – microservices need first-class cloud infrastructure to run smoothly and seamlessly, which may also come at a cost
- Cost – you should consider all the expenses connected with preparing and running the software
- Tech expertise – you should have access to developers who are able to set up and handle a product based on microservices architecture in the long run, and have extensive knowledge of systems and tooling. Remember that they are still more difficult to find, and thus more expensive.
Should I choose monolithic or microservice architecture?
You might have impatiently waited throughout the article to get the answer to this question – so here we go!
We will provide you with a list of cases or project types that will be well-fitted with either of these two options.
You should choose monolithic architecture if you are planning to build:
A small app
If the project is simple and you want to get it running quickly, monolithic is the way to go. You will have just one codebase to take care of, and to be true, you really don’t need more unless the application grows.
Moreover, if you are convinced your app will not scale (of course, you may never be 100% sure about it), there is no need to go into microservices at all.
With a minimum viable product your goal is to gather feedback from the market instantly, especially if it is a highly competitive one. Other functions may be added later. If your product is still in the ideation phase, you can quickly iterate and shift to microservices in the future.
Nevertheless, MVP can be also done with use of microservices.
You should choose microservices architecture if you are intending to set up:
A large-scale app
If your software involves a multitude of users, customer journeys, and functions, microservices are the best choice, because they will facilitate iterations. It is also useful in the case of rapidly evolving apps that need enhanced scalability and easily added new functions. Choosing the monolithic approach in this case would mean you have to develop many aspects from scratch.
A big data app
Apps based on big data are usually pipeline-oriented, which means that every stage of the pipeline is responsible for each subsequent stage of data processing. These stages may easily be managed, with each being a microservice of their own.
A real-time data processing app
Apps like Netflix, YouTube, or Soundcloud are based on microservices, because the publish-subscribe messaging pattern used in this type of architecture is just perfect for them.
A CPU-intensive app
If your app handles CPU-intensive processes like NLP or geolocation, it’s better to choose the microservices architecture, because it helps to avoid running these processes every time developers work on the software.
Migration from monolith to microservice architecture
If you want to enjoy the advantages of adopting microservices architecture, as more and more companies do, you don’t have to build everything from scratch. Yes – it is possible to migrate your existing software!
This means, among others, removing duplicate data, providing a single and unified view, and improving the control and synchronization of the systems.
The main reason one may want to move to microservices is scalability. However, scaling rarely used components may in fact be a waste of time – the first functions that should be migrated are those used the most frequently.
How can you perform this migration? What is the best way to build microservices? There are several steps. Let us briefly guide you through them!
1. Identification of logical components
The components should be understood as logical sets of data objects and the actions performed on them by the system, as well as the jobs performed. The first step involves identifying these modules as separate instances and grouping them into categories.
The components chosen for migration in the first place should be ones that are used by the most users and most frequently, have the fewest dependencies on other components, or their performance is too slow.
2. Flattening and refactoring components
After the unique identification and grouping of the abovementioned components, the groups should be organized internally.
Some data and functions may be merged, if their scope or goal is the same – in the final system there should be just one microservice responsible for one functionality, and there are multiple services.
This may be especially tricky when you decide to merge a few monolithic applications together. You should also take into consideration the data formats, data types, their accuracy, and data units – all should be organized according to one common pattern.
The same data may perform different jobs, which doesn’t mean they should duplicate.
3. Identifying component dependencies
After the previous step, it is important to determine which components are influencing other ones – this can be performed thtough an analysis of the source code, as well as using tools that allow you to automate this process.
4. Identifying component groups
The components must then be structured into cohesive groups that could be later transformed into microservices.
5. Creating an API for remote UI
The remote user interface in the microservices architecture is designed as the only way of communication between the system, including its components and users. It should be planned in a way that allows for easy scaling in the future.
In this step, the developers should provide a unified API, because everything that happens within the system depends on it.
The stateless and versioned API should be able to handle all data-access cases supported by apps that will use it and all data objects represented in the system.
6. Migrating groups of components to macroservices
Previously designed groups of modules should be moved from the monolithic system into separate thematic projects with separate deployments (macroservices). It is an interim step that will eventually lead to microservices.
7. Migrating macroservices to microservices
In the final move we have to break down migrated macroservices into microservices. They may contain more than one of the initial components. Then we should deploy and test the entire new system.
It may all sound a bit sophisticated, but we’ve got you covered – at Naturaily, we have implemented several migrations from monolith to microservices so, working with us, you’re in the best hands.
In this article, we have broken down the differences between the monolithic and microservices architecture, indicating their pros, cons, and use cases.
Definitely lightweight and scalable service oriented architecture is a very promising direction when it comes to the development of complex and evolving applications.
Soon the pros of monolithic systems will not be enough to balance their cons, although this historical approach will be still used for some purposes mentioned in the text.
So, if you want to try the microservices and Jamstack approach in your business, feel free tocontact us to talk about your needs and requirements.