Microservices get adopted as if they were a capability: "we need to scale, so we need microservices." That framing is backwards. A microservice is not a benefit; it is a cost you pay to purchase specific, narrow benefits — independent deploys, independent failure domains, independent scaling. The costs are incurred immediately and every month thereafter. The benefits only materialize under measured conditions most systems never meet. The engineering question is whether the purchase price is justified, and the default answer should be no.
The operational cost math
Every service is a standing operational liability, not a one-time extraction cost. Count what each deployable costs per month:
per-service recurring costs
build pipeline + artifact storage
deploy job + environment definitions
monitoring: dashboards, alerts, log ingestion
secret rotation and access reviews
dependency updates and vulnerability scanning
on-call ownership, runbooks, paging paths
test infrastructure and CI time
plus coordination costs that grow with n:
contract changes across service pairs (n² edges)
schema migration coordination
distributed tracing correlation
version skew between deploy windows
rollback orchestration across servicesMultiply every row by n services. A system with 15 services is not 15× a monolith's
ops — the coordination rows grow superlinearly, and each service boundary introduces
failure modes the monolith never had: network timeouts, serialization, retries, circuit
breakers, partial failure states. The p99 of every cross-service call now includes TCP,
TLS, and queue latency, forever, per hop. That is not an implementation detail; it is
the physics of the choice.
What the money buys
The three purchased benefits, stated as narrowly as they deserve:
- Independent deploys — one team ships without a release train. This only pays if teams, deploy permissions, and on-call actually align with the service split.
- Independent failure domains — one component degrades without taking the product down. This only pays if the component was already flaky and you genuinely need the rest of the system up.
- Independent scaling — one component at 100× load doesn't drag siblings. This only pays if capacity curves actually diverge, measurable in CPU and latency per component.
If none of these three are true at a measured level, you are paying microservice prices for monolith behavior.
When the monolith wins
The monolith beats services in every situation where those three benefits don't apply — which is most situations:
- One request path, one team, one deployable. Every "benefit" is theoretical. The monolith's in-process calls are faster, its rollback is one unit, its failure mode is one blast radius you already own.
- Strong consistency requirements. A monolith can wrap a flow in one ACID transaction. Services force a saga — compensating actions, visible intermediate states, reconciliation jobs — for the same business result.
- Small teams. The coordination overhead (contracts, versions, tracing, on-call rotation across services) eats the productivity the split was supposed to buy. Two teams of three do not have enough independent work to justify fifteen deployables.
The honest test is a spreadsheet, not a diagram: list the recurring costs per service (pipeline, monitoring, on-call, dependencies) and the coordination costs per pair, and ask what measured benefit pays that bill this quarter.
The strangler fig: splitting honestly
When a split is justified, do it the way a strangler fig replaces a host tree — incrementally, from the outside in, without ever performing a big-bang rewrite:
1. wrap the monolith behind a facade (its public API stays identical)
2. pick the module with the worst measured pain (scale, deploys, ownership)
3. extract it as a library first — same code, new boundary inside the monolith
4. then as a service behind a narrow, versioned interface
5. route traffic to the new service; leave the monolith serving the rest
6. repeat; retire the monolith's module only when the service has proven its p99The tell-tale of the wrong order is the team that split two services before drawing a single endpoint contract — whose "architecture" now lives in a wiki no code enforces. That is not incremental extraction; it is ceremony with a blast radius.
The verdict
Microservices are a cost center with a purchase menu. Default to one deployable; make the seam first; extract one component at a time behind a narrow interface; and require a measured, specific constraint — divergent scaling, real failure isolation, or team-scale coordination — as the price of admission. When the constraint is real, the strangler fig pays for itself. When it is vibes, the spreadsheet tells the truth: you are paying n pipelines for a diagram.