The Internet is filled with articles that sing the praises of microservices, and more than three-fourths of developers say they are using microservices in at least some of their applications.
The fact that microservices are popular, however, doesn’t mean they are always the right architectural solution for a given application. Although microservices have a lot of benefits to offer, they can also create challenges in areas like observability, security, and beyond.
So, before jumping on the microservices bandwagon, it’s critical to understand the pros and cons of microservices architectures. This article does that by briefly defining microservices, then discussing the three biggest advantages and disadvantages of using a microservices-based design.
Microservices are a type of software architecture that breaks application code and functionality down into discrete, loosely coupled units that communicate with each other over the network. This makes microservices different from so-called monolithic applications, in which all application components run as a single, tightly integrated program.
There are many ways to go about designing and implementing microservices. You don’t need to use a certain programming language or a special platform or infrastructure to create microservices apps. Nor is there a minimum number of services you have to create for your software to count as a microservices application. As long as you break the application into discrete, loosely coupled parts, it’s a microservices app, no matter where it’s deployed or exactly how you define each microservice.
If I had to explain why microservices have become so popular in recent years, I’d point to three key advantages that they offer: scalability, ease of deployment, and fault tolerance.
Microservices help applications to scale in two main ways.
First, microservices make it feasible to scale individual parts of your application in response to fluctuations in demand. For example, if there is a spike in login requests to your app, you can create more instances of the microservice that handles authentication. Because you only need to scale up this particular part of the application, scaling is faster and more efficient than it would be if you had to create more instances of a full application.
Second, because each microservice in an application is typically small, spinning up additional instances (or spinning down unnecessary ones) is faster and easier than spinning up a complete application. There’s less code to deploy, and less compute time needed.
Beyond facilitating scalability, the small size of microservices means that they are easier to deploy in general. Deploying a new version of a monolith requires moving a fairly large amount of code into production, then spinning up the application. Plus, you’d also have to build, stage, and test the entire monolith before you could deploy a new version, which also significantly slows down the process.
With microservices, deployment is faster and less complicated because you only have to deploy one microservice at a time. Typically, you can update one microservice in your app while continuing to use older versions of other microservices.
Because microservices break applications into discrete parts, the failure of one microservice doesn’t typically cause the entire application to crash. In this way, microservices create fault tolerance.
On balance, it’s important to recognize that fault tolerance alone doesn’t guarantee application reliability. If a critical microservice fails, the application may effectively stop functioning, even if the other microservices keep running. For instance, if your authentication service goes down, users won’t be able to log in, so the app will still experience a critical disruption.
Still, microservices provide some ability for applications to continue working even when part of the application fails. Users who are already logged in, for example, would most likely be able to continue using the app even if the authentication service failed. That beats having a monolith where everything fails completely due to a failure in any one part of the app.
On the other hand, microservices can pose challenges. The biggest are management complexity, observability challenges, and heightened security risks.
Managing any type of application is challenging, but managing microservices apps is especially challenging.
The reason why is simple enough: microservices mean that there are more moving pieces within your application. By extension, there is more to configure and more to deploy. (Indeed, although deploying each microservice is simpler than deploying a monolith, the fact that you have to deploy each microservice separately means you end up having many more deployment processes to plan and manage.) There is also more room for things to go wrong due to misconfigurations, malformed requests between microservices, infrastructure failures, and so on.
Observing microservices applications – which means collecting and analyzing data from them in order to understand their state – is harder than it is with monoliths, for two main reasons.
The first, and simplest, factor is that there is more data to collect, and more sources to collect it from, because you are dealing with multiple microservices. With a monolith, you’d typically have only a handful of data sources (like an application log and a server log) to deal with.
Second, to observe microservices effectively, it’s critical to be able to correlate and compare observability data from your various microservices. Thus, you face the challenge not just of collecting more data from more sources, but also of figuring out how to put all of that data together in a way that provides meaningful context. Modern observability tools can simplify this process to an extent by automatically interrelating data from discrete microservices, but you’ll still need to configure observability rules manually in some cases to gain as much insight as possible into your application.
There is nothing inherently insecure about microservices. In fact, in some respects, you could argue that microservices are more secure in the sense that the breach of one microservice doesn’t necessarily mean your entire app is breached.
On the other hand, the fact that microservices are more complex, and that they introduce more moving parts to an application, means that securing them is harder. You have more configurations to worry about, which means there is a greater risk of misconfigurations that could create security vulnerabilities. At the same time, it can be harder to detect anomalies within the complex patterns of communication between microservices. That means attacks are not always as visible.
On top of this, microservices typically require the use of additional layers of infrastructure, such as an orchestrator and a service mesh. By extension, microservices create a larger attack surface, which also heightens security risks.
All of these security challenges can be addressed, but they require more effort than you’d typically need to secure a monolith.
To decide whether microservices are right for you, weigh what’s most important in an app. Are benefits like scalability, ease of deployment, and fault isolation worth more than the challenges of managing, observing, and securing microservices?
There’ no universally right or wrong answer to that question. But there is a right or wrong answer depending on your circumstances. Deciding when – and when not – to use microservices hinges on answering that question for yourself.
Chris Tozzi has worked as a Linux systems administrator and freelance writer with more than ten years of experience covering the tech industry, especially open source, DevOps, cloud native and security. He also teaches courses on the history and culture of technology at a major university in upstate New York.
Anyone who develops applications built on microservices architectures understands that APIs are a foundational element that must be secured. To learn more about our how Checkmarx can help you secure your APIs, click here.