Macro microservices and Zombie APIs
For those who tout Monoliths I present this article.
You may be tempted to shout "but the concerns in the article aren't about monoliths, they are about microservices!" And you would be wrong.
Both of these problems are not inherent to microservices. In fact, they are actually inherent to microservice impostors. Which is to say, they ALSO plague monoliths. And when they hit monoliths, they hit harder.
Before I dive in, I want to re-iterate... while I like Microservices architecture, I am not a person who believes that any one architecture or solution is inherently superior. It truly does come down to the specifics of the projects and team working on it. And I want to re-iterate that, because I know that what follows is a scathing indictment of people who are anti-microservices. Which typically (but not always) means that they are pro-monolith.
So, I'm going to start by tackling why I believe that these problems are actually not microservices related, and then explain why they should be seen as a bigger concern for monoliths and end on why I think these terms are being coined and used in conjunction with microservices specifically.
Microservices Going Macro
This is described as; when a microservice grows beyond it's intended, initial scope, and starts becoming more difficult to manage. But, in my opinion, this is something which is only really a threat with hybrid services. IE - Services which are not true microservices to start. Though I will concede, if the entirety of an application at it's inception is small enough and well enough defined to have started life a true microservice then this could also be a problem.
But, a "true" microservice should be well enough defined in scope that changes should not really run this risk. And, if you have a larger application ecosystem with a microservices architecture there is really no reason to needlessly expand the scope of an existing microservice; you simply create a new microservice for the new functionality.
I'll admit, on this one I'm being a bit of a pain in the butt and sticking to some rigid definitions here. But this is a big part of why I often advocate for microservices architecture. It forces you to deal with the sort of headaches which might stop you from spinning up a new microservice when they are needed. If the infrastructure was properly considered when the solution was architected you shouldn't need to worry about things like communication, authentication, registering the service with your API gateway and so on. And as such, there would be no reason to violate your microservices architecture by expanding your services' scope.
In short, actually implementing a true microservices architecture should prevent this scenario from happening.
In my mind, this point is blaming microservices architecture for a problem caused by not actually implementing a microservices architecture. This is a monolith design problem, foisted on so-called microservices by implementing a hybrid strategy.
Zombie API
This is described as happening when an employee leaves a company and leaves a vacuum in knowledge resulting in an API which exists but is not maintained any longer because the expertise has left.
And guess what? This is very similar to the last problem. A proper microservices strategy actually helps to mitigate this whereas the more monolithic the solution gets the bigger the problem becomes.
How does architecture mitigate knowledge loss? Simple. Firstly, nothing about architecture, in general, prevents an employee from leaving and thus leaving a potential vacuum of knowledge. So, all other things being equal, the rate of incidence of this occurring would be the same regardless of the architecture decision. So, all we have left is the impact of the departure.
Microservices architecture, by design, decouples a lot of the concerns in code and focuses the code base on a smaller domain. A smaller domain with loosely coupled code should be easier for a developer who is new to the project to assimilate it.
Therefore the impact of losing that knowledge is constrained by the architecture in microservices where it is unbound in monolithic code. While monoliths can still be loosely coupled and the code can be well segregated to achieve a similar outcome, the fact that there is no architectural constraints enforcing those concerns means that monoliths, on average, have a harder time recovering from such a loss of talent.
Bigger Problems for Monoliths
Why this is all a bigger issue for monoliths might already be clear, but I'll restate. Monoliths start out bigger and more complex. Monoliths and even hybrid solutions also tend to lack a clear definition for the domain of the API/application. This lack of definition is what makes the solution spiral out of control.
While it is difficult to do microservice "right", especially around defining the scope. The fact remains; with microservices you are at least making the definition of the scope a part of your design process. It is a consideration from the start. And this once again places constraints and mitigates the "damage".
And while it is less likely the totality of the API in a monolith will become a "zombie", it is no less common to have one or two who completely own particular parts of a monolith than it is to have one or a small number of devs responsible for a particular microservice. So the question is really about how easy it is to bring that code "back into the fold" when talent leaves.
As mentioned before, that will generally be easier with microservices because of the constraints.
In fact, all that differentiates microservices from monoliths is the addition of constraints at an architectural levels. You are architecting boundaries into your application. Those boundaries enforce decoupling and shrink the scope of the individual projects. That may be a simplification, but it is sufficient for explaining why these problems aren't actually specific to Microservices.
So Why Do Microservices Take The Blame?
So the last question becomes; if Microservices actually mitigate all of these issues, why does the linked article and these terms exist?
For Zombie APIs it is pretty simple. By shrinking the boundaries you end up with more projects where the totality of the API can be orphaned by the loss of a single employee. Had the project been part of a monolith instead, then the same amount of knowledge is still lost, it just wouldn't be 100% of the monolithic API.
Also, observability drops. Microservices tend to be in separate projects in source control. It is lot more obvious that a project has been orphaned when you look at all of your repos and see that an entire project has had no commits in years. It is a lot harder to casually notice that a particular file within a broader project or a particular section within a file hasn't been touched in a similar amount of time.
In a monolith, you often don't notice that code has been orphaned until you find a bug and the Git Blame points to an employee who left years ago. And that, to me, is a MUCH bigger problem.
On the problem of microservice growing beyond their scopes... the issue is that monoliths don't typically have any defined scope. All approved changes are "in scope". If there is no boundary, there is no way to observe that you've crossed it. The problem ABSOLUTELY exists. It is simply, "out of sight, out of mind". Or "that is just the nature of software development".
By contrast, when you build a hybrid microservice or when you think you're building a microservice but you aren't being sufficiently granular in your scopes, then you have blurry lines. Often, where the lines drawn are not well understood or there isn't a consensus there can be issues down the road.
I also think, with microservices being a popular trend, there are a lot of strongly opinionated people jumping on the bandwagon and trying to control the direction and interpretation of the architecture. This in turn leads to a lot of angry employees publicly venting when a design doesn't follow their vision.
When someone says that X users a microservices architecture, you'll get the vultures swooping in and tearing that opinion apart. But, when someone says that Y is a monolith, very few people will stop to scrutinize. For instance, I couldn't find anyone refuting the claim that Stack Overflow was built on a monolithic architecture. And while it certainly isn't pure microservices, I think I make a pretty good argument that it is also not a true monolithic application. On the flipside, you can find OH SO MANY people arguing over what the actual architecture of that Amazon service that "stopped using serverless functions" actually is.
Conclusions
Microservices is still a popular buzz word. As such there are a lot of voices on the topic and a lot of loud ones. It is unsurprising that it is churning out a host of new terms and ideas and that some of them are catching on.
While I don't think that the thoughts around these terms are accurate I also don't think that they are bad things in general. For instance, the fact that we have a term for Zombie APIs but not a monolith equivalent is shining a light on code abandonment in general which may yield some useful tools or practices or architecture changes in the future.
And while I'm less hopeful that we'll ever contain scope creep in applications, I think it is a good thing that the topic is still finding ways to be relevant.
At the end of the day though, I still contend that there is no right answer. As I stated before, these problems are generally worse in monoliths because there are no inherent constraints in the architecture. This doesn't mean that teams can't mitigate these in other ways. And there is no doubt that Microservices is a more complex architecture. So, using it simply to mitigate these issues is likely to create others.
The most important thing is to actually architect your solution. Think about the problems and potential areas of concerns and come up with either an architecture or processes which avoid or mitigate the risks most relevant to your project.
Comments
Post a Comment