← Back to Blog

The Microservices Tax: How One Scale-Up Cut Cloud Costs 38% by Consolidating to a Modular Monolith

When a scale-up's engineering velocity slows down, the reflex is almost always the same: "We need to hire more engineers."

Nine times out of ten, it isn't a talent problem. It's an architecture problem — and more specifically, an architecture that's charging interest on every single deploy.

I call it the microservices tax: the compounding cost of operational complexity you took on before your organization was big enough to need it.

The audit

I was recently brought in to review a Python backend at a growing scale-up whose delivery had ground to a crawl. The team was convinced they were under-staffed.

What I found instead: a relatively straightforward business domain had been carved into 14 separate microservices — each running its own FastAPI instance, inside its own Docker container, communicating via HTTP through an internal API gateway.

The symptoms were textbook:

  • Latency overhead from network hops between services that had no business being separate.
  • Brutal onboarding — a new engineer needed roughly three days just to get the full system running locally.
  • An inflated AWS bill, driven by redundant database connections and cross-AZ data transfer fees that nobody had budgeted for.

The diagnosis: distributed, not decoupled

Here's the core issue. The team had paid the full operational price of microservices — network complexity, deployment choreography, observability overhead, duplicated infrastructure — without ever collecting the organizational benefit those services are designed to deliver.

Microservices exist to let large numbers of teams deploy independently, on their own cadence, without stepping on each other. That's an organizational scaling solution. This team had fewer than 50 engineers. They weren't decoupled; they were just distributed.

The fix: a modular monolith

We spent two weeks consolidating the system into a modular monolith. This is the part people misunderstand: it is not a return to a big ball of mud.

The codebase stayed split into clean, isolated domain modules with enforced boundaries — the same logical separation the team had wanted all along. The difference is that those modules now execute inside a single runtime process, instead of fourteen services shouting at each other over the network.

The results (30 days later)

  1. Cloud infrastructure spend dropped 38% — almost entirely from eliminating redundant connections and cross-AZ traffic.
  2. Time-to-deploy collapsed from a fragile, multi-stage CI/CD pipeline to a single 3-minute action.
  3. Developer onboarding went from three days of setup pain to a git clone and docker compose up.

No new hires. Same product surface. A faster, cheaper, more onboardable system.

When microservices actually earn their keep

To be clear — this isn't an anti-microservices argument. The pattern is excellent when the problem is genuinely organizational:

  • You have hundreds of engineers who need to ship independently.
  • Different parts of the system have genuinely different scaling profiles.
  • You're running polyglot teams with different runtimes and release cycles.

If that's you, the operational cost is a fair price for team autonomy. If it isn't, you're paying enterprise overhead for a startup-sized problem.

The question worth asking

Before you sign off on the next round of hiring to "fix velocity," it's worth asking a harder question:

Are you optimizing for your actual team size — or building for a Netflix-scale problem you don't have yet?


At adaleo, architecture audits like this are what we do: we look at where your Python and cloud infrastructure is quietly taxing your velocity, and we fix the root cause rather than throwing headcount at the symptom. If your costs or delivery speed feel out of line with the size of your team, get in touch — happy to share what we'd look at first.