Distributed systems
Microservices: a resilient promise?
An application is not resilient. It is resilient to something.
Cristiano Rego Barros
5 min read
Originally published on Medium
In today’s software engineering landscape, microservices have become one of the most celebrated architectural styles in the community. With that popularity come many arguments for adopting them. Some of them go along these lines:
- “Applications built with microservices perform better”;
- “Microservices speed up development”;
- “Microservices architecture is resilient”;
- “Microservices architecture is fault tolerant”;
- “Microservices are scalable”;
- “Migrating from monoliths to microservices solves availability problems”.
Hearing claims like these, microservices look very attractive. It can seem that all you need to do is migrate an application to this architecture — or start with it from day one — to get an application that is performant, scalable, available, resilient, fault tolerant, secure and fast to develop.
What software engineer wouldn’t be drawn to that story, right?
But is all of this true? Is using this architecture enough to achieve all these characteristics? If I start my application with just two services, will it be resilient and fault tolerant?
I can tell you right away: no, no and no. Simply adopting a microservices architecture does not transform an application on its own.
Even though I’ve already said these claims aren’t true, I’d like to dig into these characteristics and how each one relates to microservices. Since there are many, in this article I’ll focus on “microservices architecture is resilient” and “microservices architecture is fault tolerant” — more precisely, on resilience as an architectural characteristic.
What is resilience, anyway?
Before looking at resilience in microservices, it helps to understand what resilience is and what it means to be resilient. In physics, resilience is the property some materials have of returning to their original shape after undergoing elastic deformation. Figuratively, the dictionary defines it as the ability to recover easily from or adapt to misfortune or change.
In software engineering and architecture, resilience refers to an application’s technical ability to meet its delivery requirements while carrying out its activities without being impacted by an adversity (internal or external).
So why would microservices architecture be considered resilient and fault tolerant?
The argument rests on a comparison with monolithic architectures, in which internal components are all grouped into a single unit and suffer from a burden called coupling.
Coupling comes into play because many components live in a single unit, all connected, so healthy parts can be affected indirectly by parts that are failing.
Since microservices promote decoupling between components, the architecture would be more resilient and tolerant of partial failures than the monolithic pattern.
So can we say that microservices are really more resilient than monoliths?
The network takes its toll
Not necessarily. First, it is worth noting that in monolithic architectures most internal components communicate in memory, in a lightweight way. In a distributed architecture, on the other hand, components usually communicate over the network — a heavier form of communication that is more prone to failure.
Peter Deutsch’s eight fallacies of distributed computing offer great points showing that this architecture won’t be resilient on its own:
- The network is reliable;
- Latency is zero;
- Bandwidth is infinite;
- The network is secure;
- Topology doesn’t change;
- There is one administrator;
- Transport cost is zero;
- The network is homogeneous.
These fallacies remind us that every call between services can fail, that response times can vary, that the network can go down, that external dependencies can be unavailable — and that all of this must be anticipated if we want our application to be truly resilient.
However, the fallacies focus only on network communication. Even if mechanisms are put in place for these risk points, resilience still won’t be achieved as a general characteristic of the architecture.
Resilient to what?
Resilience isn’t limited to a single control point, and that is why nothing is 100% resilient. Resilience depends not only on non-functional factors but, above all, on the application’s functional factors — which makes it relative to what each piece of software sets out to solve.
For different services, resilience takes different forms, as in the examples below, where each scenario has a different need:
| Scenario | Resilience need |
|---|---|
| Business requirement: news portal | Content must always be up to date and never stop being delivered. |
| Authentication service | Keep authenticating users even if the authentication service is down. |
| Architecture changes | Allow changes to happen without impacting the service’s clients. |
| Security | The system must mitigate attack attempts quickly and stay stable for other users. |
Conclusion
In the end, we can ask again: is microservices architecture, by itself, resilient? I can say without a doubt: definitely not.
Of course, microservices offer more promising possibilities for implementing resilience than other architectural styles. But resilience isn’t a flag you set to true in your application, nor does it come down to adding a tool that handles a single point of failure. It is a far more complex, broad and deep characteristic than the opening claims suggested.
My advice: investigate your system and understand the domain to find its control points, rank them by priority and address them as you can. And never stop checking those control points to make sure they are delivering what is expected of them.
Remember: software architecture is made of decisions and trade-offs, not ready-made promises.
This is a broad topic full of nuance. If you have experiences, lessons learned or disagreements, let me know. Let’s learn from each other and enrich the conversation about architecture and resilience.