Microservices trade simplicity for independent scaling and deployment. Learn where the boundaries go, what you gain, and the significant costs most teams underestimate.
Why: microservices split a system into small, independently deployable services owned by separate teams — the real benefits are independent deployment and scaling and team autonomy, not "smaller code." When: adopt them when independent scaling or many teams working without stepping on each other is a genuine, present need. Where: the benefits are organizational and operational; if you do not need those, you are paying the cost for nothing.
MICROSERVICES: many small services, each independently deployable + scalable,
each owned by a team, communicating over the network.
+ deploy + scale each service independently
+ team autonomy (own service, own release cadence)
+ fault + tech isolation (a service can use a different stack)
- it's now a DISTRIBUTED system — the network is unreliable
The wins are ORGANIZATIONAL/operational. No such need -> stay monolith.Why: the single hardest and most important decision is where the service boundaries go — split by business capability / bounded context (from DDD), not by technical layer — because bad boundaries create a distributed monolith where services are so chatty and coupled you get all the cost and none of the benefit. When: draw boundaries around cohesive business domains that change together and own their data. Where: this is where DDD’s bounded contexts pay off directly.
SPLIT BY BUSINESS CAPABILITY (bounded context), not by technical layer:
GOOD: [ Orders ] [ Payments ] [ Shipping ] each owns its data + logic
BAD: [ Controllers svc ] [ Services svc ] [ DB svc ] (a layered monolith
spread over a network)
Bad boundaries -> a DISTRIBUTED MONOLITH: services so coupled and chatty you
pay all the distributed cost for none of the autonomy. Boundaries decide
whether microservices help or hurt.Why: microservices turn in-process simplicity into distributed complexity — network calls fail, data is spread across services (no easy transactions), and you now need service discovery, distributed tracing, and orchestration — so the operational tax is real and continuous. When: adopt them only if your team can fund that tax (platform, observability, CI/CD, on-call). Where: each service owning its own data means cross-service consistency needs sagas and eventual consistency, not database transactions.
The microservices tax (ongoing, not one-time):
- the network fails: retries, timeouts, circuit breakers everywhere
- data is distributed: no cross-service transactions -> sagas + eventual
consistency (see the Integration & Event-Driven checklist / Design course)
- operability: service discovery, API gateway, distributed tracing, CI/CD
per service, container orchestration
- testing + debugging span many services
Can your org fund this continuously? If not, a modular monolith wins.