And even more often, folks use microservices, but make them so coupled that you can't really run/test/hack one without running all the others... Basically creating a distributed monolith.
people really underestimate the power that vertical scaling can achieve, along with the long tail that microservices can bring. (The more calls between services you need to handle x, the more likely it is that you get into a case where one call takes exceptionally long)
Actually I think microservices serve as a tool for enforcing modularity. When pressure is high, corners are cut, and when unrelated code is easy to reach (as in case of a monolithic codebase), it's easy to fall into temptation - a small dirty hack is faster than refactoring. And when you consider different maintainers, it's easy to lose track of the original monolith architecture idea in all the dirty hacks.
Microservices enforce some kind of strict separation, so in theory nobody can do anything that they're not supposed to. In practice, a lot of coupling can happen at the microservices level - the most common symptom being some weird isolated APIs whose only purpose is to do that one thing that another service needs for some reason. Those kind of ad-hoc dependencies tend to make services implementation-specific and non-interchangeable, therefore breaking modularity.
So, in conclusion, some approaches are easier to keep modular than others, but there seems to be no silver bullet for replacing care and effort.
Couldn't agree more. Often times folks are using microservices to achieve good modularity at a cost.