Microservices vs Monolith: Which Should You Start With?
Key takeaway
Start with a modular monolith. Microservices solve an organizational problem — many teams deploying independently — and buy distributed-systems complexity you pay for daily. Split when team coordination, not code size, becomes the bottleneck.
Microservices are an organizational pattern that gets adopted as a technical one. The architecture lets independent teams deploy independently; if you have one team, you get the costs and none of the benefit.
What a monolith gets right
- One deployment, one log stream, one place to set a breakpoint.
- Transactions across your data without distributed coordination.
- Refactoring across module boundaries is a compiler-checked change, not a multi-repo migration.
- Dramatically lower infrastructure and observability cost.
What microservices genuinely buy
- Independent deploys — teams ship without a shared release train.
- Independent scaling for a component with a very different load profile (video transcoding, ML inference).
- Fault isolation, if — and only if — you design the failure modes deliberately.
- Freedom to use a different language or runtime where it truly matters.
The bill for going distributed
Every in-process call you turn into a network call gains latency, partial failure, retries, timeouts, and a serialization format to version. You will also need distributed tracing, centralized logging, service discovery, and a deployment pipeline per service. None of that ships features.
The modular monolith middle ground
Build one deployable, but enforce module boundaries inside it: each module owns its tables, exposes an explicit interface, and never reaches into another module's internals. You get the operational simplicity of a monolith with seams already cut — so when a module does need to become a service, it lifts out in weeks rather than requiring an archaeology project.
Signals it's time to split
- Multiple teams are blocking each other in a shared release process.
- One component's scaling profile is forcing you to over-provision everything else.
- A specific module has genuinely different availability or compliance requirements.
- Build and test times have grown past the point where fast feedback is possible — and you've already tried fixing that directly.