Microservices or Monolith? The Real Cost of an Architecture Decision
"We use microservices" became a status symbol at some point. On LinkedIn profiles, job postings, startup pitches. As if using microservices was an achievement in itself.
This article corrects that misconception. Microservices is a powerful tool — but like any tool, it causes damage when used by the wrong hands at the wrong time.
What Is a Monolith? Why Did It Get a Bad Reputation?
A monolith is an architecture where all application components are packaged as a single deployable unit. User interface, business logic, data access layer — all in the same codebase, running in the same process.
Monolith:
┌─────────────────────────────────┐
│ Application │
│ ┌────────┐ ┌────────────┐ │
│ │ Auth │ │ Orders │ │
│ └────────┘ └────────────┘ │
│ ┌────────┐ ┌────────────┐ │
│ │Products│ │ Payment │ │
│ └────────┘ └────────────┘ │
└────────────────┬────────────────┘
│
PostgreSQL
Why did the monolith get a bad reputation? Because problems accumulate as it grows. A small change can affect the entire system. If one module leaks memory, the whole application crashes. Different teams working on the same codebase break each other's changes. Scaling is coarse-grained — you have to scale the entire application when only the payment module is under load.
But these aren't inevitable properties of a monolith. They're properties of a poorly organized monolith.
What Are Microservices?
Microservices splits the application into small, independently deployable services. Each service focuses on a single business capability, manages its own database, and communicates with other services via API.
Microservices:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Auth │ │ Products │ │ Orders │
│ Service │ │ Service │ │ Service │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
Users DB Products DB Orders DB
┌──────────┐ ┌──────────┐
│ Payment │ │Notification│
│ Service │ │ Service │
└────┬─────┘ └──────────┘
Payment DB
Each service is deployed independently. Updating the auth service doesn't affect the products service. If the orders service is overloaded, you scale only that. Different teams work autonomously on different services.
Sounds perfect. So why doesn't everyone use microservices?
The Real Cost of Microservices
Microservices aren't free. You need to see the price you pay clearly.
Distributed system complexity. What is a function call in a monolith becomes a network request in microservices. Networks can be slow, fail, or time out. Partial failure scenarios emerge — what happens when the orders service is running but the payment service isn't responding?
Inter-service communication. Synchronous (REST, gRPC) or asynchronous (Kafka, RabbitMQ)? Every choice has trade-offs. Async communication provides resilience but introduces eventual consistency — payment confirmed but order status not yet updated.
Data consistency. In a monolith, database transactions guarantee data consistency. In microservices, each service has its own database. No ACID guarantees for operations spanning multiple services. Solving this requires complex approaches like the Saga pattern.
Operational overhead. 10 services means 10 separate deployment pipelines, 10 separate log sources, 10 separate monitoring configurations. You need to know Kubernetes. Set up distributed tracing. Evaluate service mesh options.
Developer experience. Local development becomes harder. Docker Compose configuration bloats to run 10 services simultaneously. When a feature spans multiple services, coordination cost increases.
When to Choose Which?
The right question isn't "microservices or monolith?" but "how much complexity can I carry right now?"
Choose a monolith when:
You're still discovering what your product will be. Wasting time on architecture decisions before reaching your first users delays solving the real problem. Your team is small (under 5-10 people). In small teams, the cost of managing service boundaries exceeds the benefit. You don't fully know your domain yet — incorrectly drawn service boundaries are far more expensive than poor modularity in a monolith.
Consider microservices when:
Different components show dramatically different scaling needs. The team has grown and multiple teams are experiencing friction in the same codebase. You know your domain well and can confidently draw service boundaries. You have operational maturity — infrastructure to set up CI/CD, monitoring, and distributed tracing.
Modular Monolith: Often the Best Starting Point
There's an option between the two extremes that's often overlooked: the modular monolith.
A single deployable unit, but divided internally with clear module boundaries. Each module has its own area of responsibility, with restricted access to other modules. When the time comes, service boundaries are already drawn, making the transition to microservices much less painful.
Modular Monolith:
┌──────────────────────────────────────┐
│ Application │
│ ┌───────────────────────────────┐ │
│ │ Auth Module │ │
│ │ (has its own repositories) │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ Orders Module │ │
│ │ (only accesses public APIs) │ │
│ └───────────────────────────────┘ │
└──────────────────────────────────────┘
Shopify grew for years with a modular monolith. Stack Overflow still handles millions of requests with a monolith. These companies aren't falling behind — they're making conscious choices.
The Amazon and Netflix Story
Amazon and Netflix played a big role in popularizing microservices. Both told success stories of transitioning from monolith to microservices.
But remember this: Amazon made the transition in the early 2000s, after reaching the scale where the monolith was genuinely painful, with hundreds of engineers. Netflix transformed in 2008 when moving to streaming, when the need for high availability was crystal clear.
Both experienced the problem first, then adopted the solution. If you're adopting the solution before experiencing the problem, you're actually acquiring a new problem.
Architecture decisions aren't irreversible — but every transformation has a cost. The best architecture is the one that solves your current problem, doesn't block your growth, and sits at a complexity level your team can carry.