“Monolith or Microservices” is not the conversation we should be having.
Representing a loosely defined pattern or set of principles with a single word is hard. It doesn’t work very well. As it turns out, people latch on to the term, project their own meaning, then pass it on to others to do the same. Along the way, the term’s true semantics are lost (*cough* Agile *cough*).
What’s the difference between a monolith and a Microservice anyway? The name “Microservice” seems to imply that some measure of size is the differentiating characteristic. Folks will tell you that Microservices are really small. How small is “small”? An insect? A pony? Lichtenstein? Ok, “small”. At what size does a Microservice become a monolith?
Above, is an example of an unproductive conversation. It’s a conversation I’ve heard countless times regarding the false dichotomy, or at least poor framing, of a wholly unnecessary “Monolith or Microservices” debate.
Forget about “Microservices”.
Instead, think about discrete parts of your system, and how they might benefit from being deployed, scaled and/or tested independently. Runtime isolation has a lot of advantages.
Think about your team, and how its dynamics might improve with clearer boundaries, ownership and responsibilities. When a codebase gets sufficiently large, and difficult to hold in one’s head, stewards tend to emerge. This is a natural tendency that creates organic, implicit boundaries. Explicit boundaries can reduce bottlenecking, coordination overhead and tentativeness.
Think about how challenging it is to reason about your large system, and how it might be easier for your engineers to grok in smaller pieces. The size and complexity of your codebase impacts onboarding, and the likelihood that an engineer from another team is going to be willing to contribute a patch.
Think about risk isolation, and how seemingly benign changes can have broad side effects. Consider the principle of least privilege, and how large portions of your system may have access to sensitive data or operations that they probably shouldn’t have.
Think about how encapsulating just a few key pieces of your system in discrete services might be valuable, because you don’t need to decompose your entire monolith to realize the benefits of decoupling a critical portion of it. Modularization is not a whole hog proposition.
Each of the points above have (many!) counterpoints, because engineering is about tradeoffs — I’m not advocating on behalf of any architecture. These are just examples of more concrete and productive conversations we could be having about the tradeoffs of writing software with decoupled runtimes.
I encourage your team to have conversations like these, rather than “which fashionable architecture should we adopt today?”