It also depends on how much functionality you consider to be “one thing”.
It also depends on how much functionality you consider to be “one thing”.
I thought microservices is a solution to scale development teams, not for traffic.
If you have a horizontally scalable monolith, it can scale pretty much as far as you want. If you split services along functional boundaries (i.e., vertical) then a split from 1 to 2 services will in the extreme best case scenario give you 2x scaleup; further splits give you less. So: If load is the issue, work on horizontal scaling, not microservices.
What am I missing?
At some point, you have servers, that say, pre compute complex internationalization logic, and therefore are almost databases, and you want to keep them separate. Other times splitting requests that have very different memory vs cpu requirements into different boxes helps. And this is just for performance/costs.
The scariest issues are all operational though: Suddenly my giant fleet is misbehaving, and a rollback means 10K servers get hit, and I am not exactly sure what is going on. Having the functionality separated a little will do a lot of good.
Now, from there to needing microservices is a pretty big gap, but the lone uberservice can get very scary under the wrong circumstances, and the probability approaches 1 as the codebase gets really big.
I am all for dividing services after technical requirements; and certainly any non-O(1) memory requirements for instance one may want to look at a dedicated service.
When we get into the things you say, the definition of "service" gets more important too. Is it separate DB, or only separate k8s pod or VM, or what... If the only constraint is to make computation efficient and robust, the solution space is bigger if one does not add the "should fullfill the microservices ideology" as another constraint.
With microservices on k8s I think it is pretty common for each VM to have many open connections to 15+ databases though, so not sure if I got that particular point.
As you add more functionality to a system, it gains different workloads, which have different needs (e.g. different storage solutions) and need to scale at different rates (e.g. one part of the system is very memory hungry and another is very compute heavy).
As your system gets larger, it's usually more important that its various components are well isolated, both on software and hardware axes, e.g. container isolation vs isolating across different physical zones/regions. Sometimes that isolation happens for security/compliance reasons, e.g. PCI.
As your business grows, you will need to build functional solutions that require different toolchains and platforms. You will acquire other businesses that have built on different platforms. You will not require all of your acquisitions to rewrite all of their software into your monolith.
With extra work, you can solve for many of these problems within a monolithic architecture, but those solutions will typically introduce similar complexities as microservices (e.g. talking to many datastores, composing your monolith of many coordinating processes, configuring independent nodes of your monolith differently, provisioning independent nodes appropriately, etc).
My experience in software is that we draw false dichotomies between approaches and the reality is that they will tend to converge when you put in the effort to consider and address the shortcomings of each approach.
Microservices have their own challenges apart from network communication etc between medium sized services that yiu refer to.
For instance lack of easily available consistency, sometimes needing to basically implement multi-service transactions (see SAGA pattern) and so on... if services are a bit larger, such problems occur much more seldom.