A team adopted microservices and now every feature touches five services, five pipelines and a distributed debugging session. Which boundaries were justified, and when is consolidation the improvement?
Show the full answer Hide the answer
Which boundaries are justified
A service boundary earns its cost when at least one of these is true:
- Genuinely independent scaling. One component's resource profile differs by an order of magnitude — image processing, search indexing, a fan-out worker.
- A different failure domain that matters. The component must be able to fail without taking the rest with it, or must be isolated so its failure is contained.
- A different rate of change with a different risk profile. A component changing daily should not deploy through the same pipeline as one changing quarterly with regulatory review.
- A genuinely separate team ownership where the interface is stable and the coordination cost is lower than the coupling cost.
- A different technology requirement that cannot be satisfied in the main codebase.
Team size alone is not a justification. Neither is "it is a different domain concept", which describes a module boundary rather than a deployment boundary.
When consolidation is the improvement
When the split produced coordination rather than independence. The test is concrete: can one team change, deploy and roll back without telling the others? If the answer is no — if releases have a required sequence, if a schema change is a cross-team event, if every feature needs all five — the boundary is delivering cost without benefit.
Independent deployability is the entire point of a service boundary. A boundary that does not deliver it is pure overhead, whatever the diagram says.
What consolidation buys and costs
Buys: one deployment, one transaction boundary, one debugging session, local calls instead of network calls, and the removal of a coordination tax paid on every feature.
Costs: a larger blast radius, one failure domain, and the loss of any genuinely independent scaling — which is a real cost only if the independent scaling was real.
That trade is favourable when the services shared a release cadence anyway, which — if every feature needs all of them — they did.
The intermediate position
A modular monolith: strong module boundaries with enforced dependency rules, one deployable. It preserves the design discipline that made the boundaries useful and removes the distribution that made them expensive.
It is also the state from which a genuine service extraction is easiest, because the boundary already exists and only the deployment changes — which is why it is the better starting point than a distributed system built before the boundaries were understood.