Pixel Myth
← Field notes
Architecture

Microservices: the hidden bill

Architecture field note

Splitting the monolith fixed coupled deploys and created a new problem: nobody could tell why a request failed.

Splitting a monolith sounds like an architecture decision on paper. In practice it is a financial decision because every new service is a cost. A network boundary, a contract between components, a new thing that can fail in ways the monolith could not, plus ongoing operational expenses.

You pay for the complexity in operational overhead and engineering time spent debugging. You pay in traces and logging systems. You pay in deployment coordination and debugging complexity. The payoff only happens if you reduce coupling enough to move faster and deploy more independently.

We started by instrumenting the monolith thoroughly before proposing splits. We wanted to see what was actually coupled and what only looked coupled because it lived in the same codebase. The answer is usually that real data dependencies are much narrower than organizational boundaries suggest to managers.

The boundaries that make sense are where the data stopped being shared between components meaningfully. That is where the contract is already implicit in the data flow. We looked at eleven proposed services in the original plan and found only four where that held true.

Those four got split into separate services. The other seven stayed in the monolith with clear module boundaries. None of those seven has migrated to service status in the two years since, which suggests the evaluation was sound and the decision was right.

The lesson: do not split for architecture purity or for team boundaries. Split where you actually have independent data flows and minimal coupling. That usually means fewer services and ones that actually matter to the business and the team.