In the beginning, there was monolithic architecture. Most apps were built as a single unit, with all the processes tightly connected to each other. This caused a lot of trouble with deployment, bug-fixing, and updating, which is why there was a huge necessity to divide this structure into smaller parts.
The term “microservices” was first introduced in 2011 at a workshop of software architects. They used it to describe the type of a common architectural style that they were using at that time. The idea of the technology itself appeared even earlier, in 2005, when "Micro-Web-Services" was brought up during the Web Services Edge conference.
One decade later, microservices architecture has become hugely popular because it can address many current IT challenges such as app performance speed-up, scalability, and fast testing. But is everything that rosy? Let’s take a close look at microservices and consider both their pros and cons.
In a nutshell, a microservices architecture is one of the structural styles of a service-oriented architecture (SOA) that organizes a complex app as a bunch of smaller apps — microservices — that connect with each other through language-agnostic APIs.
Microservices possess certain features that make them suitable for large apps. They are:
Microservices are efficient in cloud apps, serverless computing, and apps with lightweight container deployment, as these software types require a scalable and decentralized continuous delivery that this architecture can provide.
As we mentioned, the monolithic architecture was hard to deal with in complex apps, so the main purpose of a microservices architecture is to build and maintain such applications as a whole made up of smaller parts. Microservices smoothly cooperate with each other, and each performs a separate function. We consider functions here as independent services that can be updated, fixed, or deleted without affecting the rest of the app.
Splitting an app into small self-contained blocks facilitates its development, deployment, and further maintenance. All microservices can be built, deployed, and managed independently from each other, and can use not one but several programming languages and tools depending on the needs they are to meet.
Also, a more concise codebase for each element makes scaling, publishing, updating, bug-fixing, and testing more manageable. Each microservice works on its own, so there’s no need to access the source code while changing the functionality. You can easily modify, test, and then deploy microservices independently, delivering the app faster as a result.
Now, as a large-size app is divided into smaller parts performing their own functions, each microservice can be developed by a separate team. At first glance, it can seem unnecessary and costly, but in fact, there are real advantages:
Another advantage of microservices is their process for identifying and fixing any problems with app performance. If one module fails, its developers have the opportunity to use another service redirecting that function to it, so the app will run without any disruptions. The improved fault isolation means that more complex apps don’t get significantly affected by a single small error, which also reduces the risk of downtime.
As a result, with the help of microservices, developers have the ability to reverse all updates, change the app’s components, and leave the rest of the app free from redeploying.
Since microservices are basically small independent apps inside a bigger one, developers can easily scale the app up and down depending on the current needs and requirements. If detached, the system allows smooth operation in the event of major changes.
Additionally, it’s possible to scale not only the entire app with new microservices but also each module separately. If a piece of code in any of the microservices becomes a bottleneck that reduces performance, it can be run on more powerful hardware to correspond to the required performance or run on multiple machines to process data in parallel.
Thus, microservices have proven to be an ideal alternative for companies working with a variety of platforms and devices.
Thanks to the loosely coupled structure and absence of solid connections between microservices in an app, each module can be written in a different language or with the help of different tools. It allows you to select the suitable stack of technologies for each function without having to worry about their incompatibility. There’s just no such thing.
Besides, existing microservices can be adapted for use in different contexts without having to create completely new modules.
Microservices architectures work great with continuous integration/continuous delivery (CI/CD) pipelines. We can create different procedures for different configurations of each microservice, especially for large-scale projects. Depending on the team composition and the type of service, different deployment patterns can be implemented.
While developing an app, the team should consider all aspects of the CI/CD and plan the solutions for possible difficulties in order to solve unique problems associated with microservices. The most important things to address are:
Microservices allow individual teams to develop, test, distribute and review them quickly. The ability to balance the workload between teams, combine workflows, and automate manual work considerably speeds up the development process.
If we take into account all the advantages mentioned above, we see that targeting a specific microservice instead of an entire app when updating or bug-fixing allows you to focus more on improving your business performance. Working with each separate module independently also allows you to more accurately analyze if this function really works for users and, if not, to either upgrade it or get rid of it right away.
At the very first stage of development, microservices do save you from having to re-render large apps in their entirety. But with time, as such an app grows and gains more functionality, the number of microservices also rises, and the connections between them can become tangled. It creates multiple management structures and increases the complexity of using all the functions at the same time.
It’s important to carefully manage the app’s microservices during development. In such cases, developers may have to write more code to avoid failures and disruptions. Over time, problems will inevitably arise, costing you more money and resources.
DevOps is an essential part of working with microservices, so before you start to integrate them, you need to build a solid DevOps culture.
While working on microservices, each development team starts operating as an independent business. This is great because teams can work independently and exercise more control with increased productivity. However, it also means that every development team needs to maintain a consistent lifecycle of their microservices, including maintaining a robust API and an independent testing strategy. For some agencies, it can become quite a challenge.
Another important issue here is that you need to determine whether your teams have enough experience to successfully operate microservices-based projects. Developers need to have a deep understanding of how to work with loosely coupled structures, including their launch, testing, and bug-fixing.
In addition, you will definitely need DevOps managers for each team, who will become one of the most valuable assets as you scale.
Also, adopting microservices often involves moving decision-making processes from top managers down to the teams themselves. For some companies, it can be hard to accept such power transitions in their organizational hierarchies.
When the various types of relationships inside your application are clear and easy to distinguish from one another, a microservices architecture will contribute to the quality of development indeed. But what if these connections are unclear?
That’s when “different languages for different microservices” can become a problem. In the case of incorrectly configured relations between the modules, fixing and updating the application built with microservices becomes more difficult than refactoring a monolithic architecture. In addition, the interface updates should be discussed with all the teams working on microservices. Also, using different languages for different environments will be ineffective if you need to migrate the functionality of some microservice to another one.
This disadvantage is extremely important for small businesses who want to build a microservices-based app. Microservices will need to communicate with each other, which means a large number of remote calls. This results in increased network latency and processing costs, sometimes even more than what you might expect to pay when using conventional architectures. Developers will need to take this issue into account, building possible solutions that aim to reduce the number of calls to avoid disruption. This also equals higher costs.
Also, microservices consume more additional resources, since each service needs its own central processing unit (CPU) and runtime environment. More tools, more hardware, more servers, more APIs — you will have to use it due to the lack of uniformity in a microservices architecture.
This issue also stems from the “different languages for different microservices” approach: with each service using its own technology stack, the demand for resources grows. You need to account for all things needed for the development, management, updating, and maintenance of each module.
In contrast to a monolithic architecture, microservices brought up some noticeable security challenges due to the huge volume of data exchanged between modules. The logical chain looks like that: you work with multiple small containers — you expose more of your modules to the network — you expose more of the system to potential threats.
Many security concerns are related to the API gateway implementation. With distributed microservices applications, it seems obvious to build a single security policy into components that will be shared by all the services. However, different modules can require different security permissions according to their functions, so a single policy may be the reason for breaches and hackers’ intrusion into the system.
The high replicability of microservices is also worth mentioning. Since the source code of one module can be used in different projects, it can present easy access for hackers, which can snowball into a big problem.
Comparing the pros and cons of microservices, you can see that for smaller businesses, a monolithic architecture will work better as it’s simpler, faster, and cheaper. As such businesses grow and their app starts to need scaling, it can still be migrated to microservices when you need to address new business needs.
The bigger the company, the more obvious the need is for microservices, as they help to ensure uptime and scalability along with accommodating more ambitious business goals. In such cases, microservices can provide the necessary infrastructure for building a highly efficient digital solution.
The pros and cons of microservices-based architectures really depend on the type and needs of your project. Microservices are scalable, flexible, and resilient — that’s good. At the same time, they can easily become complex and expensive to maintain. Choose wisely!
Get weekly updates on the newest design stories, case studies and tips right in your mailbox.