Microservices has become almost a default approach to building scalabale API infrastructure. You know it’s hit saturation when you start to seeing pro-monolith posts on Hacker News. We’ve hit a nadir in the hype cycle as too many orgs rushed into microservices without understanding why they needed it and if it was worth the investment.
The simple solution to this is to aim for a comfy middle gound. Just write modular code and using an artifact repository. It’s a model I’ve rarely seen adopted even though it’s much easier than microservices and serves many of the same purposes. You can have individual dev teams, with their own repo, own test suites, backlogs, own stakeholders, etc all working at their own paces. They build modules (jars, nuget packages, npm modules) and deploy semver versioned artifacts to a repo like Nexus or JFrog. Any frontend/consumer applications can build towards versions of those modules and upgrade on their own schedule. Only the consumers need to worry about deployment.
This gives you the organizational flexibility but not the infrastructure overhead. You can think of it as logical microservices on a physical monolith. This also has the distinct advantage of greatly reduced IO since you can make simple procedure calls that might otherwise be HTTP request.
The discriminating factor that makes microservices necessary is if these individual services have divergent hardware or runtime needs. Squeezing CPU-bound processes on the same VM as IO-bound or memory-bound can start to cause conflict. And, of course, mixing languages is difficult (language runtimes really). The other big complexity comes from the dependency tree. Once you’ve got clients which depend on conflicting versions of libraries, it can get difficult to manage. Being very deliberate with your semver labels can mitigate. Patch releases should all be compatible. Minor releases can require some regression testing. Only a major release should incur a refactor and coordinated upgrade. If this gets to be too much overhead, then you’ve probably already hit the level of scale that requires microservices.
If you’ve organized your modules in a sane fashion, then refactoring into microservices should be straightforward.