Iโve watched three startups burn months splitting a monolith into microservices before they even had product-market fit. Every time, they regretted it. This is the post I wish someone had shown them.
Every startup Iโve seen adopt microservices too early has regretted it. Every single one.
The fantasy
โWeโll have independent services that deploy separately, scale independently, and teams can work without stepping on each other.โ
The reality
You now have:
- 12 repos instead of 1
- A service mesh you donโt understand
- Network calls where function calls used to be
- Distributed transactions that fail in ways you canโt reproduce locally
- A Kubernetes cluster that costs more than your developers
- 3 engineers spending 40% of their time on infrastructure instead of features
The math doesnโt work for small teams
Microservices make sense when you have 100+ engineers and the monolith is genuinely slowing you down because teams are blocking each other.
If you have 5-20 developers, a well-structured monolith is:
- Faster to develop โ no network overhead, no service discovery, no API contracts between teams
- Easier to debug โ one stack trace instead of distributed tracing across 8 services
- Cheaper to run โ one server instead of a Kubernetes cluster
- Simpler to deploy โ one pipeline instead of 12
โBut Netflix uses microservices!โ
Netflix has 12,000+ engineers. You have 8. Netflixโs problems are not your problems.
Also, Netflix started as a monolith. So did Amazon. So did Shopify (which is still largely a monolith and handles Black Friday traffic just fine).
The real problems microservices solve
- Team independence โ when 200 engineers canโt merge to the same repo without conflicts
- Independent scaling โ when your search service needs 50x the compute of your user service
- Technology diversity โ when one team genuinely needs Python ML and another needs Go for performance
If none of these apply to you, youโre adding complexity for no benefit.
What to do instead
Start with a modular monolith. Structure your code into clear modules with defined boundaries:
src/
modules/
auth/
billing/
notifications/
products/
shared/
database/
middleware/
Each module has its own routes, services, and data access. They communicate through defined interfaces, not direct database queries. When (if) you need to extract a service later, the boundaries are already there.
The extraction rule
Extract a microservice when:
- A specific module needs to scale independently (you have metrics proving this)
- A team is genuinely blocked by the monolithโs deploy cycle
- A module needs a different technology stack
Until then, enjoy your simple deploys, your single database, and your stack traces that actually make sense.
The conversation you should actually be having
Instead of โshould we use microservices?โ, ask:
- โWhatโs our biggest deployment bottleneck right now?โ (Usually itโs tests, not architecture)
- โWhich part of the codebase changes most often?โ (Thatโs your candidate for extraction โ later)
- โHow many developers are blocked by each other?โ (If the answer is โrarely,โ you donโt have a monolith problem)
Most teams that adopt microservices prematurely spend more time debugging distributed systems than building features. A well-structured monolith with clear module boundaries will take you further than you think โ and when you do need to extract a service, the boundaries are already there.
Related: Monolith vs Microservices ยท Docker vs Kubernetes ยท What is a Microservice? ยท Stop Over Engineering Side Projects