Microservice architectures seem to be the latest craze. When in doubt, bet your software architecture on microservices. They sure will deliver everything but the kitchen sink.
Or maybe think twice? Because microservices like all technologies and paradigms come with a price. And this price is not cheap – especially if you haven’t dealt with distributed architectures before.
The question then is: When to pay the price? When will microservices have a chance to deliver more benefits than they will cost?
Here’s a suggestion for a checklist. Ask yourself…
- Availability: Will the solution need to be highly available? Will downtime hardly be an option for releasing better code with more features and/or less bugs into production?
- Contexts: Will the solution cater to the needs of several, quite different user groups?
- Size: Will the codebase be so large that complete rewrites will hardly be an option in case the legacy has become too big and the brownfield too deep?
- Teams: Will development be done by multiple, possibly distributed teams or more than maybe 5-6 possibly distributed developers?
- Distribution: Will the solution’s runtime efficiency benefit from a distributed architecture, e.g. for scalability or security reasons.
The more questions you answer with Yes the more likely jumping on the microservices bandwaggon will lead to better results.
What do I mean by better results? Which problem are microservices to solve anyway?
To me it’s very clear: Microservices are containers for code to help with sustainable productivity. They belong to the realm of clean code development. They are a kind of module like classes and libraries are modules, too.
Microservice architectures are supposed to help with lifetime requirements, not runtime requirements. Don’t use microservices if you „just“ have a runtime efficiency problem with your monolith.
The more checkmarks you made, though, the more interesting microservices are as an architectural option.
- They help with availability because they partition code into small truly independently deployable units. Each microservice is a process which can be started, stopped, updated, restarted individually. At least in principle. This might help to keep the overall application running while parts of it are down for maintenance, or even can be updated in the background and then switched over to. This kind of microservice architecture I call a wave, because to me it looks like a standing wave: that is a wave of constant form and fixed location but whose water molecules are in constant exchange; they flow through the standing wave.
- If quite different communities of users will work with a software system then it’s likely they have very different views on how data should be handled and even named. Microservices help to mirror such diversity in code by assigning different microservies (or groups thereof) to different bounded contexts. Instead of using a one-size-fits-all database the data is split across multiple databases owned by different microservices. This helps the important architectural value of decoupling.
- Even if you strive for clean code eventually you’ll have to face a codebase which is very hard to adapt to new requirements and/or technologies. Then only a rewrite will get you back to high productivity. But if a monolithic codebase is too large, then that’s not an option. Better to foresee this and architecture the code so that rewrites remain an option. Not complete rewrites, but partial rewrites. That’s what can be achieved with microservices. Each microservice should not grow beyond a size where a rewrite is not an option anymore. Otherwise it would be unjustified to call them microservices. And since microservices are much more decoupled than e.g. libraries it should be easier to replace them with a completely new version without any surrounding services being affected.
- Microservices are islands of code with very clear boundaries at design time as well as runtime. That makes it easier to assign complete microservices to different team members or teams. They could even decide on their own which programming language/stack to use. With microservices the existing team organization can be better mapped to independent code artefacts to avoid conflicts with Conway’s law. So if the team structure itself is not monolithic then a non-monolithic code structure can help to avoid frictions.
- Finally, since microservices are distributed by nature they also might help with runtime efficiency problems like your grandfather’s client-service architecture did. A need for distribution alone does not justify a microservice architecture in my view, though. But if distribution is needed anyway, then an even more fine grained distribution won’t hurt that much and can be chosen to kill two or more birds with one stone. Especially if the development team is already familiar with code distribution. The additional price to move from client-server to more services wouldn’t be that big.
Think about this the next time someone touts microservices as the only solution. Maybe you agree because several of the checklist items are to be marked. Or maybe you now can disagree with substantial arguments because none or just a single item could be marked.
In any case I think such a checklist can help to ask more questions and enter more meaningful discussions before a fundamental and costly decision in favour or against microservices is made.
Image source: pixabay