Skip to content
CESAR ZANIS
Back to Blog
TechnologyArticle

When Not to Use Microservices: The Hidden Tax of Distributed Complexity

Few architectural movements have burned more venture capital and enterprise IT budgets over the last decade than the premature adoption of microservices.

We have all seen the movie: an organization with 15 to 25 software engineers and a moderate traffic profile (a few hundred requests per second) decides that its existing application is "legacy." Inspired by conference talks from Netflix, Uber, or Amazon, the architecture team announces a greenfield rewrite: they slice the domain into 40 tiny microservices, each with its own Git repository, its own CI/CD pipeline, its own Docker container, its own database, and a complex Kubernetes service mesh gluing it all together.

Eighteen months later, the outcome is almost always the same:

  • Feature velocity has collapsed: Adding a single new attribute to a customer invoice now requires coordinated pull requests, version bumps, and deployment choreography across six different microservices.
  • Debugging requires a detective agency: When a customer checkout fails, no single engineer understands the end-to-end state machine across asynchronous queues, retries, and compensating transactions.
  • The cloud bill has tripled: Even though user traffic grew by only 15%, AWS/GCP costs exploded due to redundant container headroom, Cross-AZ network transfer fees, and observability tracing ingestion.

As Martin Fowler and Sam Newman, two of the earliest pioneers who documented microservices, have repeatedly warned: microservices should almost never be your starting point.

1. What Problem Were Microservices Actually Invented to Solve?

Microservices were not invented to make code "cleaner" or faster. An in-memory function call inside a single process executes in nanoseconds and cannot fail due to a dropped network packet. The moment you split that function call across two network-separated microservices, execution time jumps by five to six orders of magnitude (milliseconds), and you immediately inherit the Fallacies of Distributed Computing: network partitions, timeouts, out-of-order messages, and partial failures.

Why, then, did companies like Netflix and Amazon adopt microservices? To solve Conway’s Law at massive organizational scale. When you have 1,500 engineers across 180 autonomous squads committing code simultaneously, coordinating a single monolithic deployment binary and a single shared database becomes an organizational bottleneck. Microservices trade away runtime simplicity and infrastructure efficiency in exchange for organizational decoupling at massive headcount.

If you have 15 or 30 engineers and 45 microservices, meaning every developer is juggling two or three services, you are paying 100% of the Distributed Complexity Tax while collecting 0% of the organizational benefit.

2. The Five Hidden Taxes of Premature Microservices

Before splitting a system into distributed services, every CTO and Principal Architect must quantify the five compounding taxes that come with every network boundary:

DimensionModular Monolith (Single Deployable)Premature Microservices (30+ Services)
1. Data ConsistencyNative ACID transactions (BEGIN / COMMIT / ROLLBACK)Eventual consistency, complex Saga patterns, outbox tables, and orphaned state
2. Latency & NetworkIn-process memory calls (nanoseconds, $0 transfer cost)HTTP/gRPC serialization, mTLS, retries, and Cross-AZ cloud data transfer fees
3. DevEx & RefactoringIDE compile-time refactoring across module interfaces in secondsBreaking API contract migrations across multiple repos and consumer versions
4. Observability CostStandard application logs + single APM agentExpensive distributed tracing (OpenTelemetry spans) across dozens of network hops
5. Cloud FinOpsShared CPU/RAM pool scaled smoothly as one unitFragmented idle CPU/memory headroom multiplied across 30+ separate deployments

Even cloud giants have publicly recognized this math. When Amazon Prime Video’s audio/video quality monitoring team consolidated their distributed microservices and serverless step-functions back into a single monolithic process, they famously reduced their infrastructure cost by over 90% while scaling to higher throughput, simply by eliminating the absurd overhead of serializing and shipping high-volume state across network boundaries.

3. The Smart Default: The Modular Monolith

Rejecting premature microservices does not mean writing spaghetti code where controller files directly query 200 database tables at random. The false dichotomy between a "Big Ball of Mud Monolith" and "Microservices" ignores the superior middle path practiced by elite engineering organizations like Shopify: the Modular Monolith.

In a Modular Monolith, all code compiles and deploys as a single operational artifact (or a small handful of coarse-grained services), but the internal codebase is strictly partitioned into isolated business domains:

  1. Enforced Module Boundaries: The Billing module cannot directly import internal classes or query the private database tables of the Inventory or Identity modules. It can only interact with them through explicit, versioned public interfaces in code, checked automatically by linter rules in CI/CD (such as ArchUnit, Packwerk, or TypeScript project references).
  2. Logical Schema Separation: Even within a single PostgreSQL cluster, each domain module owns its own tables (or schemas), preventing accidental cross-domain JOIN coupling.
  3. Zero Network Overhead: Because all modules run inside the same process and memory space, deployments are atomic, local developer environments spin up in seconds on a laptop, and cloud bills stay lean.

And notice the best part: if a team cannot maintain clean boundaries inside a Modular Monolith with compiler enforcement, they will never maintain clean boundaries across 40 microservices. They will simply build a Distributed Monolith, where every service calls every other service synchronously, and if one service goes down, the entire company goes down.

4. The Three Legitimate Triggers to Extract a Microservice

Once your Modular Monolith has clean boundaries, extracting a specific module into an independent microservice takes days rather than months. You should pull that trigger only when at least one of these three concrete conditions is met:

  1. Asymmetric Compute or Resource Profile: One specific module requires specialized hardware (such as GPU inference, heavy video transcoding, or massive in-memory graph processing) that scales on a completely different curve from your core CRUD API.
  2. Strict Fault or Compliance Isolation: A critical payment-processing vault (PCI-DSS scope) or high-availability ingestion webhook must remain up even if the rest of the application is undergoing maintenance.
  3. True Organizational Autonomy at Scale: Your engineering team has grown past 50 to 80+ engineers, and independent business lines need completely separate release cadences and technology stacks.

Build for the scale and team size you have in the next 18 months, not for the fantasy scale of a 5,000-engineer tech giant.

Continue reading: explore Scalable Architecture Guide and Cloud FinOps in Practice: Cutting AWS and GCP Spend.

Cesar Zanis / Technology

Good ideas keep the conversation going.

Share this article or publish the visual deck to your Stories and Feed.

WhatsApp ↗LinkedIn ↗X ↗
Slide 01 of 06
Microservices solve an organizational problem, not a coding problem.

Conway’s Law explains why companies with 800 engineers split systems into independent services. When a 12-person team adopts 40 microservices, they import massive overhead with zero benefit.

Source: Martin Fowler, Microservices Trade-Offs & Conway’s Law.

On compatible mobile browsers (iOS Safari and Android Chrome), the primary button opens your native share sheet with all cards and copies the caption. On desktop or other browsers, download the numbered .zip bundle or save individual PNGs.

Files are numbered in publication order.

Image preview
1080 × 1920 (9:16 Stories) · PNG
Cesar Zanis
Written by·Software Architect & Fractional CTO

Cesar Zanis

15+ years leading software architecture, database performance, FinOps, and applied AI across enterprise operations. Built and scaled an engineering organization from zero to 20+ developers.

15+ yrs experience-50% Cloud FinOps99,99% SLA0 → 20+ Devs

Enjoyed this article?

I publish practical analyses on software architecture, FinOps, data, AI, management, and economics directly on LinkedIn.

Continue Reading

Need help implementing this?

Czanix can help your company turn theory into practice. Schedule a free strategic call.