To move fast, software development teams should use small independently-released microservices. But how small should they be?
Microservices are somewhat like camping: the first time you do it, there is a lot of uncertainty and stress. What should you bring in your backpack? You end up overthinking it and bringing many things you don’t need.
With microservices, we need to choose the right service boundaries: what goes into which service. Sometimes we create too many services that become a maintenance nightmare. And it is tough to course-correct and rearrange the architecture once services are in production. Recently someone asked:
ivanjaros hi. i have a microservice that handles users(entities). should i set up a custom microservice for authentication or should i just stick the logic into this user service instead and keep it simple?
So when should we create a new microservice? There are many articles from reputable sources talking about this:
- Martin Fawler’s Monolith First
- Ben Morris’ How big is a microservice?
- Microsoft’s Designing a DDD-oriented microservice. (I don’t agree with all recommendations from that article, but it is a good read)
Back to ivanjaros’ question about whether he should split the users and authentication handlers into two services or not, the short answer is: if you have a concrete product roadmap showing that the authentication code will have a lot more logic within, say, six months, then splitting it now can be OK. Otherwise, it’s best to leave both in the same service – but making sure they are still kept modular and decoupled.
The reason for keeping them in the same service by default is that more likely than not, your infrastructure is not 100% automated. Unless you have 100% of your platform automated and spinning up, and maintaining a new service doesn’t increase ops work, new microservices come with a cost. So you should not do it prematurely.
Creating new microservices is similar to adding an abstraction in the code: consider what are your real use cases and break down your domains of concern accordingly. Don’t overdo it. Don’t build overly complex interfaces because of hypothetical use cases such as “let me add a database middleware here just in case we move from Oracle to MySQL 10 years from now”.
Similarly, if you use, say, Amazon S3 to store data files, you probably shouldn’t create a CloudStorage microservice to sit in the middle between your other services and S3, unless you have a clear plan for moving soon to a different cloud. Otherwise, if you create new microservices to support imaginary future requirements, you end up with a large chunk of wasted code that requires some non-zero maintenance time.
Factors to consider while deciding when to create a new service
How many people are working on this code base, now or soon? The more people working on the same code base, the more likely it is for an engineer to waste time because somebody else “broke the build”, crashed the development environment, caused a flaky test, or introduced a bug that will delay the production rollout. If problems like this are routine, it is time to split the services (and probably fix your tools).
Are there people working in the same service from distant time zones? It is much easier to tap your colleague on the next desk to help debug the broken build than to wait for someone in Europe to wake up and figure out what’s going on. Distributed teams should ideally work on distinct microservices.
How painful is it to release these services? We all know what services are more likely to cause headaches during production rollouts. You probably want to avoid adding a new functionality to problematic services. New features usually need fast follow-up iterations, but that will not happen if you co-host with your headache-inducing service.
How much maintenance overhead results from creating new services? Despite years of improvement, as of September 2017 when I left, even our SRE team at Google had not yet managed to fully automate the setup and maintenance of new services. There is always some extra ops overhead for new services, and often a lot more than we assume at first.
As you may have read before, I am working on an upcoming open-source project to help with challenges in this space. If any of this resonates with you, let’s connect and chat!