The microservices fallacy - Part 7
This post discusses actual reasons that justify the use of microservices.
I hope you had a good start in the new year 2021! After a two weeks break, we will continue the blog series regarding the fallacies of microservices (and what to do about it).
In the previous post we discussed the last fallacy from the list – that microservices make technology changes easier. In this post we move on and leave the fallacies behind. In this post we discuss actual reasons that justify the use of microservices and draw an interim conclusion.
Having debunked the fallacies regarding microservices, we need to ask: When do we actually need microservices?
Unless you are a hyperscaler, there are only two major settings in which microservices unfold their strengths 1:
- You need to move fast
- You face very disparate NFRs
Let us look at them one by one.
The most important reason to pick up microservices is that they support you in moving faster in a highly competitive and dynamic market where speed makes the difference between success and demise.
That is probably the main reason why the hyperscalers adopted microservices. They live in very fast moving, winner-takes-all markets. This means, they need to move fast to stay on top, i.e., continuously and quickly adapt their (IT-based business) service offering to the ever-changing needs and demands of their users.
To be able to move fast, they organized themselves in market-facing capability teams. This allowed the teams to move at their own speed because – if split right – market-facing capabilities are (mostly) independent of each other. As a result cross-team coordination which typically slows companies down a lot is minimized.
If all teams need to move in lockstep due to coordination needs, at any given time the slowest team defines the speed. Without the need for cross-coordination each team can move at its own optimal speed.
But this also requires independence on the IT level. Whatever you do on the business side has a counterpart in IT today. You cannot change anything on the business side anymore without touching IT. IT is the business nervous system of any non-trivial company today. This is especially true for the hyperscalers as their business models are usually based on IT.
If you have a highly interdependent IT landscape where all parts are highly dependent of the other parts, any functional independence of the teams is obliterated by the IT dependencies. In such a setting, you need to coordinate planned changes with all teams to make sure that you do not accidentally break anything in the IT systems.
This makes you even slower than the slowest team because now you do not only have to wait on the functional level but you additionally need to synchronize all changes and make sure in effortful test cycles that nobody unintentionally broke something in the IT systems.
This was not acceptable for the hyperscalers. Interestingly enough, most of them started exactly with such a highly interconnected IT landscape. But as the pain of these dependencies became paramount they decided to rethink their IT architecture from scratch.
They decided to strictly modularize their IT systems in a way that IT modules do not cross team borders. IT modules crossing team borders means coordination, means slowing down. Thus, they strictly went for modules not crossing team boundaries.
Additionally, they wanted each team to be able to release their new features whenever they are ready, not having to coordinate their deployments with other teams.
Hence, any module needed to be independent of all other modules at development, build, test and deploy time. This way teams were able to implement and ship their stuff completely independent of all other (market capability) teams.
Theoretically it would also be possible to find an architecture that supports these traits without requiring the modules to run in separate process scopes (think, e.g., OSGi).
Yet, as the hyperscalers also had some additional requirements like, e.g., very high availability demands while at the same time elastic up- and downscaling at a rate, nobody except them experienced, they went for a modularization approach with modules that are independent at runtime, either. That is (in a bit simplified form) how they ended up with microservices as their architectural style. 2
As I wrote in the beginning of this blog series: The hyperscalers also knew (or learned quickly) that microservices impose a lot of challenges regarding all aspects of IT, that microservices are a very demanding architectural style, probably one of the most demanding styles that exist. But as they helped them to solve their quite unique business challenges they were willing to pay the price.
If you transfer the hyperscaler story to regular enterprises, it means that microservices can help you to move really fast on a business level in a highly competitive market. Still, it also requires that you set up your organization and processes in a way that enables fast, independent acting of teams.
And it means that you need to implement very rigorous practices regarding design, development, testing, deployment and operations that you usually do not need with other architectural styles – at least to that degree. And finally you must be willing to invest a lot in the training of your people (inside and outside IT).
If you are not willing to do all this, microservices will not help you to become faster. They will just make things more complicated and probably result in an IT landscape being brittler than before.
But if you are willing to pay the price and go the whole 9 yards, microservices can help you to speed up your IT and your business significantly and give you a competitive advantage in highly dynamic market contexts.
Very disparate NFRs
The second, much rarer reason to go for microservices are very disparate NFRs. Assume part of your application is used by many thousands of users at the same time who all expect high availability, including very short response times, even at peak hours (or especially then).
Another part of your application is used just by a handful of users, but due to the sensitivity of their activities that part has to meet extremely high privacy demands – that nobody but the handful of people is able to access the data as they can or is able to trigger their actions.
It would be unfortunate if you would need to implement these very disparate non-functional demands for all application parts alike. But that is what you basically need to do if you implement everything in a single application. You basically have to create the union of all NFRs and make sure that the resulting application meets all of them at runtime, no matter if just a tiny subset of the application actually needs them.
Coming back to the little example:
- The sensitive part does not have any scalability demands and very moderate response time demands.
- The public part has very moderate security demands.
Yet, shipping both parts in a single application would mean that the application needs to be capable of meeting the union of the demands. This makes the application a lot more complicated than it would need to be if the parts with the disparate NFRs could be isolated.
That is what microservices can give you: The ability to split up your application in multiple parts that each implements very different NFRs. This makes the different parts a lot simpler as they only need to care about their relevant set of NFRs. Still, you need to pay the price for the distribution as I discussed before. But it could be worth it depending on the concrete NFRs.
Be aware that you do not necessarily need to use microservices to separate disparate NFRs in isolated runtime units. Also other architecture styles do allow to implement it. But microservices are definitely one of them.
Personally, I think that this statement has a point. In its core, I think it goes back to the “moving fast” need described above. Scaling exponentially basically always happens in contexts where you also need to move fast. At least I do not know any company that scaled exponentially without facing any pressure to move fast at the same time. Still, I think it is worth to mention exponential growth as a potential driver for microservices.
But why did I not put it on the list of drivers?
The reason is that very few companies face exponential growth. I added the constraint “unless you are a hyperscaler” several times throughout this blog series. Here it applies again: For at least 99,999% of all companies this reason is irrelevant. There are simpler ways to deal with non-exponential growth than resorting to microservices, i.e., it is not a reason why you need to go for microservices.
And if you are actually a hyperscaler? Well, congratulations! But then most rules do not apply anyway that apply to regular companies and enterprises. Then microservices are an architectural style that can support you in managing your hyper-growth – probably not the only way but a valid and useful way. Just keep in mind that you need to pay the bill for all the additional measures microservices require.
The typical claims why you need microservices,
- being needed for scalability
- being simpler than monoliths
- improving reusability (and thus pay for themselves after a short while)
- improving team autonomy
- leading to better design
- making change of technology easier
all turn out to be fallacies if you take a closer look.
They only support the change of technology partially. But even there they just fight symptoms at a very high price and do not address the root cause for the problem. Thus, they are a weak relief at best. Additionally, with container technology nowadays you have everything you need for simple technology updates. You do not need a specific architecture style to implement it.
The real case for microservices is to support going fast in highly competitive markets. Microservices support functionally highly independent teams with an architecture style that provides them with complete independence from other teams all along the IT value chain.
Still, this effect only unfolds if you first organize for moving fast, i.e., go for independent cross-functional teams organized by market capabilities, adapt your governance model, let go of the “IT as a cost center” fallacy and so on.
Additionally, microservices are a way to deal with very disparate NFRs affecting different parts of an application. By splitting the application up and isolating the different parts from each other at runtime, it is possible to create much simpler parts as not all parts need to implement the union of all NFRs.
Still, you need to pay the price for creating a distributed application. Also, there are other options than just microservices to isolate disparate NFRs.
We have discussed the most widespread fallacies that I see over and over again in the context of microservices. We have discussed the actual reasons that justify the use of microservices and we have drawn an interim conclusion.
With this basis we will move on in the next post to make sense of it, to discuss when to use microservices, when not to use them and what to do instead. Stay tuned …
[Update] January 11, 2021: Added section about exponential growth after a Twitter comment by Trond Hjorteland.
Actually, the listed strengths of microservices could also be achieved by other means, i.e., without employing microservices. But microservices are one of the most “natural” architecture styles to achieve those goals. ↩︎
The fact that many of the software engineers had SOA experiences from the SOA hype in the early 2000s (including experiences regarding the shortcomings of the SOA hype), probably also influenced the decision towards a service-based architecture. ↩︎