Microservices get reached for earlier than they should on a lot of projects, often because of what a tech talk said rather than what the actual system needs at its actual size.
What a monolith gets right
Simpler deployment, simpler debugging (one codebase, one set of logs, one place to look), and far less operational overhead. For a small team and a product that’s still finding its shape, this simplicity is a genuine advantage, not a limitation to apologize for.
What microservices actually solve
Independent scaling of different parts of a system, independent deployment so one team’s release doesn’t block another’s, and the ability to use different technologies for different services where that genuinely matters. These are real benefits โ for a system and a team large enough to need them.
The cost that gets underestimated
Network calls between services where function calls used to be, distributed debugging, eventual consistency, and a meaningfully more complex deployment and monitoring setup. None of this is free, and all of it is work a small team now has to do that a monolith simply doesn’t require.
A reasonable default
Start with a well-structured monolith โ modular internally, with clean boundaries between its parts โ and split out a service only when there’s a specific, current reason to: a scaling bottleneck in one part of the system, or a team boundary that genuinely needs independent deployment. The modularity inside a monolith is what makes that later split possible without a rewrite.
