The Microservices Payoff
A look at the tradeoffs and costs of adopting a microservices architecture.
A great deal has been written recently about microservices, in particular, about how they’re not the armoured warrior princess riding in to save the wounded software prince. I think we’ve certainly reached a microservices peak with even projects such as Istio rearchitecting parts of the system to move away from a microservice architecture to a monolith.
That’s not what this article is about though. I feel that has been relatively well-covered by many other talented engineers and writers and, for the purposes of this article, I am going to assume that the reader has made a considered decision and that the use of microservices has sufficient benefits in their own use case. I further assume that the use of microservices over a modular or distributed monolith has been proven to have value. Justin Etheredge’s article is pretty good starting point if you need further clarity on that; however, I find what he says to be a slight simplification and I can think of instances where a microservice architecture may still make sense with fewer than 100 developers, but on the whole, it’s a good place to start.
If you’re still with me, and still think microservices are the right answer for your use case, the point I really want to make in this article is quite simple. If you’re going to implement microservices (in particular as opposed to a distributed monolith), then don’t dawdle. Get your CD pipelines and ability to release independently implemented as a critical priority and do everything you can to protect that ability to deploy each service independently. I can’t stress the importance of this point enough. If you don’t do this, you’re effectively paying the microservices tax to little benefit.
I should, of course, point out that the move to a microservice architecture has a significant expense associated with it, one which is often overlooked (especially by management). Much that has been written recently about microservices amply demonstrates that there is a great deal of additional complexity to be dealt with in building microservices; distributed transaction, failure modes and resiliency and significant additional complexity in testing are just a few of the additional taxes that demand to be paid.
These taxes start being paid the minute you separate into multiple processes. However, the purported benefit of multiple teams deploying independently and a reduced level of friction improving development speed won’t materialise quite so easily.
Assuming you’ve correctly identified your boundaries (if you haven’t, you won’t benefit from a microservice architecture anyway) to attain the panacea of independent teams developing and deploying code at will, you need to ensure that you are able to test your system adequately (at a microservice level). This can be quite insidious and often not even visible to management. The establishment of independent CD pipelines is expensive but rarely overlooked as this is visible not only to the engineers but the management team (agile or otherwise) that prioritises the work.
What is sometimes overlooked, however, is that, in order to deploy each component independently, it needs also to be able to be tested independently. At a very basic level, this could be achieved in a similar way to monolithic testing where the only change to the system is the service in question (and then system level tests are run). This, however, is expensive, slow and puts a chicane right in the path of independent deployment.
The really sneaky part though is that, even when you have a great CD pipeline, complete with fully automated testing and deployment through to production, your developers don’t quite trust it or are unable to complete their development without first having to run the entire system (or a significant part of it) on their desktops. This scenario is insidious because the management will seldom be aware it is taking place, after all there’s a great CD pipeline in place, right?
In such a situation, where you have adopted a distributed system, and are now paying the inherent development taxes but have yet to adopt an ability for each service to be developed, tested and deployed completely independently of others, you have the worst possible return on your investment. Therefore, you will want to minimise the amount of time you spend, and, while in this state, the teams’ (and I assume there is more than one as otherwise you probably shouldn’t be building microservices) primary concern should be to remedy all aspects of the system that are preventing complete independence of your services.
Until such time that this situation is resolved, you will continue to pay a development tax, which is often of the order of at least 20% and more commonly 40% or greater. (Yes, distributed systems are that much more complex to develop). If all you’re getting in return for this is the ability to say “but we’re cool and modern and building microservices” you might find your competitors eating your breakfast, lunch and dinner pretty soon.
Of course, if the only reason you’re building a microservice architecture is because it was the “en vogue” thing to do or have found yourself struggling to get to a point where your services truly are independent for an extended period of time, might I suggest you think about it again and consider more seriously a majestic monolith instead?