A B2B analytics company runs 40 services with 12 engineers. Deploys are independent, but a typical feature touches four services and takes three weeks to reach production. Review this architecture: what would you merge, what would you leave alone, and how would you argue it?
Show the full answer Hide the answer
What is actually required
Twelve engineers cannot own 40 services. Each service carries a fixed cost that does not shrink with its size: a pipeline, dashboards, alerts, a dependency upgrade cadence, an on-call owner and a place in everyone's mental model. At roughly three services per engineer, most of them have no real owner, which shows up as services nobody has deployed in months sitting on unpatched dependencies.
The three-week lead time for a four-service change is the number that settles the review. Independent deployability is worth paying for only when changes are usually independent. Here they are not, so the team pays the coordination cost and gets none of the benefit — the definition of a distributed monolith.
What I would merge and why it is safe
Merge along the seam where a change almost always crosses the boundary. Pull the last six months of pull requests and count co-change: any pair of services changed together in more than about half of features belongs in one deployable unit. In a fleet this size that usually collapses 40 into 8 to 12.
It is safe because merging removes a network hop rather than adding one: the failure modes disappear (partial failures, retries, version skew between the two halves) instead of moving. Keep the module boundary in code — package or namespace, with an enforced import rule — so nothing about the domain model is lost. The boundary that was worth having was the code boundary; the deployment boundary was the expensive part.
What I would leave alone
- Anything with a genuinely different scaling axis: the ingest path that handles 50x the request volume of the rest of the system.
- Anything with a different failure requirement: the component that must keep accepting data while the UI is down.
- Anything with a compliance or data-residency boundary, where merging would drag the rest of the system into the audit scope.
- A service written in a different language for a real reason, such as an existing numerical library.
These look odd in a consolidated estate and should stay odd. The test is whether the boundary buys something a module boundary cannot.
The one change that matters
Not the merge itself — the co-change measurement. It converts the review from a taste argument into arithmetic, and it keeps working afterwards as a standing signal: when two modules start co-changing, they were split wrong; when one module's changes stop touching anything else, it has earned extraction.
Common weak answers
- "Microservices are wrong for a team this size." True as a heuristic and useless in a review, because it gives no order of operations and antagonises the people who built it.
- "Merge everything into a monolith." Discards the four boundaries that are load-bearing and creates a second migration in two years.
- "Add a service mesh and better tracing." Improves visibility into a coordination cost without reducing it. The three-week lead time is not a diagnosis problem.
- "Rewrite." The consolidation is mostly deleting network calls and moving files; a rewrite converts a six-week job into a two-year one.