Goodbye microservices, hello right-sized services
If you’ve been to any conference recently or follow industry news, you have probably heard about microservices. They’re everywhere. Whether it is called SOA done right, microservices, or just decomposing big balls of mud, the hype is there, and it’s unavoidable. Even if you are not particularly interested in the subject, your client or manager may be asking you about it sooner than you think.
🔗Micro is the new black
As is usually the case with new and complex subjects, microservices have raised varied, often contradictory opinions in the developer community. Sometimes people use the same words but have different things in mind; sometimes different names are used to refer to the same thing.
Some say there’s nothing new under the sun. Others point out that we live in a different world than when SOA was first defined. Continuous Delivery, DevOps or cross-functional teams are more popular, which makes our current environment quite different from what we had only a few years ago. Even naming these things is controversial. Services, microservices, and autonomous components are all terms that have been thrown around to refer to almost (if not quite) the same thing.
For the purpose of this post, I consider the terms microservice, service and component as synonyms, leaving detailed discussion regarding the properties and differences between them out of scope. Clarifying this issue is a subject for another post. What is important here is that “the size question” comes up equally often no matter what label we put on that thing.
Each term comes with its own context, and there are ongoing discussions surrounding the definitions of these things. Over time, with some luck, that knowledge will be distilled, vocabularies unified, and beginners will have clear, consistent implementation guidelines.
But we’re not quite there yet.
🔗Does size matter?
Currently, one of the very few things that everybody agrees upon is that a component that is “small and focused on doing one thing well” is better than a big monolithic ball of mud. If you’ve worked with a huge system that was very hard to maintain, then you might agree that even if code is far from perfect, the smaller it is, the easier the work.
Smaller elements can be understood more quickly, are easier to modify and less likely to be accidentally broken. The smaller they are, the faster we can fix bugs and ship new features. If necessary, we can even throw away the whole microservice and rewrite it from scratch in a matter of weeks, instead of months or years.
It seems that size is kind of important. If it wasn’t, why would we talk about microservices and big balls of mud? No wonder that one of the most frequently asked questions regarding services is how big they should be? What is the right size? How do we know if we’re on the track?
This is where things get complicated…
🔗Be careful what you ask for
I recently had a conversation with a developer about his current project. He told me that they are doing something like microservices, but their services are not real microservices. I was puzzled. What did he mean by not real? He explained that a microservice shouldn’t be bigger than 300 lines of code, but their services were bigger than that.
New plugin I’ve been working on…Still in prototype stages... pic.twitter.com/NJ6orOw40Z— Hadi Hariri (@hhariri) December 4, 2014
There are a lot of different metrics floating around, such as being able to rewrite each microservice in 6 weeks, or having a 2-pizza team per service. On the surface, these metrics appear more meaningful than lines of code, since they don’t depend on the expressiveness of the programming language in use.
All these metrics can be useful rules of thumb, but what we often forget is the context. Each of these rules makes sense under certain circumstances. If you don’t have the same team structure, work with a less experienced team or just use a different programming language, the specific value (or even type of metric) might not provide much benefit.
More importantly, don’t forget that what you measure is what you get. If you tell everybody in your team that the limit is 300 lines of code, and you will track it, you will end up with small services. But that doesn’t guarantee your system will be easy to modify, more reliable or that you will ship features faster.
The size of components is only one of the attributes of a system that make it easy to maintain. However, by focusing mainly on size we tend to ignore more important factors and risk ending up with the same old big balls of mud, only this time they are distributed.
🔗Beyond lines of code
Fortunately, there are more meaningful things you can do. The key element is modeling services, in particular finding their proper boundaries and aligning them with bounded contexts or business capabilities. Finding Service Boundaries - illustrated in healthcare offers valuable insights and tips on how that looks in practice. In another example, a Norwegian company combined dozens of ultra-fine-grained services into just a few bigger, more focused ones.
On the surface, everything seems clear and easy, but the devil is in the details. Over time, you will identify gray areas. You will notice there’s no single, well-organized source of truth with easy-to-follow guidelines. You need to do a lot of research and heavy thinking before you decide whose advice you will follow.
For example, one of the challenges with service boundaries is that it feels natural to align them with the user interface. Explore composite UIs in more detail to understand the alternative to a service per screen approach. Another natural expectation is that organization analysis will help us discover proper business boundaries. However, organizations are constantly evolving. Mergers, layoffs, and reorganizations happen frequently. People may work on cross-functional teams or have overlapping responsibilities. In the long run, trying to align service boundaries with organizational boundaries is very hard.
Only by digging deeper into these common challenges will you gain a better understanding of how to define services and their boundaries.
🔗Focus on what matters
Rather than size, focus on service boundaries. Analyze business bounded contexts, align your services with business capabilities and focus on making sure your components are truly autonomous. In the meantime, you’ll probably find an answer to the “how big?” question that makes sense in your circumstances. You might also realize that as long as you focus on service boundaries, it doesn’t really matter how big each service ends being.
Finding the right boundaries is much more complicated than saying “each microservice has to be less than 300 lines of code.” It requires (sometimes messy) work to better understand the underlying business context. That’s why focusing on size is so tempting, even if it doesn’t provide the expected benefits.
The good news is that there’s already plenty of good advice available. More and more people share their experiences at conferences and talk about their journey from monoliths to (micro)services. You can learn from their successes and their mistakes.
However, you always need to be careful what you take away from those stories. After all, while everybody always talks about size, most people know that that’s not what really matters.
About the author: Weronika Łabaj is a developer at Particular Software, passionate about exploring new paradigms, rediscovering familiar things by looking at them from fresh perspectives and providing business value with software.