What Microservices Actually Buy You
Strip away the conference talks and microservices purchase exactly three things: independent deployment (team A ships without waiting for team B), independent scaling (the image-processing service scales without dragging the CRUD app along), and failure isolation (one service down ≠ everything down, if — big if — you've engineered the fallbacks).
Notice what all three have in common: they're solutions to coordination problems between multiple teams and wildly divergent workloads. If you have four engineers and one product, you are paying for solutions to problems you don't have.
What They Cost
The tax is paid in operational complexity, and it's charged monthly forever:
- Every function call becomes a network call — with latency, retries, timeouts, circuit breakers and partial failure where a stack trace used to be.
- Transactions become sagas. "Debit account, credit account" inside one database is trivial; across two services it's a distributed-systems research topic wearing a Jira ticket.
- Debugging becomes distributed tracing. Without serious observability investment, "why did this order fail?" turns into archaeology across six services' logs.
- Infrastructure multiplies: per-service pipelines, service discovery, a message bus, and someone who genuinely understands Kubernetes at 3am.
A distributed system is the only kind of system where your program can fail because of a computer you didn't know existed. Buy that property only when it's paying rent.
The Modular Monolith: The Default You're Looking For
The overlooked middle: one deployable, internally structured as strict modules — each owning its domain, its tables, and a defined internal interface, with boundaries enforced by tooling (compile-time dependency rules, separate schemas) rather than good intentions. You get monolith simplicity — one deploy, real transactions, a debugger that works — plus the option value: because module boundaries are honest, any module that later earns extraction (a genuinely divergent scaling profile, a team that needs independent releases) can be lifted out along seams that already exist. That's the strangler-fig logic from our migration playbook, applied in reverse.
The Decision Framework
Score honestly:
- Team size and shape. Under ~30-50 engineers or fewer than 4-5 autonomous teams: modular monolith, almost regardless of anything else. Microservices below this line solve nothing you have and cost everything you can't spare.
- Deployment contention. Are teams genuinely blocking each other's releases weekly? That's the pain services fix. If deploys are contentious because there are no tests, fix the tests — distribution won't help.
- Workload divergence. One component needing 100x the compute, GPUs, or a different runtime is a legitimate extraction candidate — extract that, not everything.
- Operational maturity. No 24/7 on-call, no tracing, no platform engineers? You don't have the licence yet, whatever the org chart says.
The resulting portfolio for most mid-market builds: a modular monolith core, plus one or two genuinely separate services where the workload demands it. That's not a compromise — it's the architecture the constraints actually specify. It's also, not coincidentally, how we deliver most fixed-price builds: boring shape, fast delivery, options preserved.
If You're Already Over-Distributed
The 2025-26 pattern nobody blogs about: consolidation. Teams merging 40 nano-services back into 6-8 sensible ones, cutting infrastructure cost 30-60% and change lead time more. The method is the migration playbook run in reverse — and the lesson is the same in both directions: the architecture should follow the organisation and the workload, not the conference schedule.
Architecture decision looming?
Book 15 minutes with architects who've built — and rescued — both shapes at enterprise scale.
Book a 15-Minute Call →