Microservices vs Monolith

Architectural tradeoff between a single deployable unit and a distributed system of small services.

Core Idea

A monolith is simple to develop, deploy, and debug. Microservices add network latency, distributed failure modes, and operational complexity — but enable independent scaling and deployment of components. The right choice depends on team size, traffic patterns, and organizational structure.

Start With the Monolith by Default

A modular monolith is the right starting point for most teams. One repository, one deployable unit, and one database let you move faster while the product is still changing.

Monoliths win when:

  • The team is small
  • The domain is still changing every month
  • End-to-end debugging matters more than independent deployment
  • Traffic is not large enough to justify separate scaling paths

When Services Start Making Sense

Microservices are justified when a boundary is already real in the organization and in the runtime behavior.

Signals that the split is real:

  • One subsystem needs very different scaling characteristics
  • A specific domain has a clear ownership team
  • Release cadence differs sharply across components
  • A failure in one area should not take down the rest of the system
  • The domain boundary is stable enough to support an API contract

What You Pay for Services

Moving to services turns local function calls into remote calls. That creates new problems:

  • Network timeouts and partial failure
  • Versioned APIs and schema migration
  • Distributed tracing and harder debugging
  • Eventual consistency between services
  • More deployment, monitoring, and on-call overhead

If the team does not have strong observability, microservices mostly turn code complexity into operational complexity.

Decision Table

QuestionFavors monolithFavors services
Team size1-10 engineersMultiple independent teams
Deploy frequencySimilar across the appVery different by domain
Data modelStrongly coupledNaturally separated
Failure isolation needLow/moderateHigh
Traffic shapeUniformOne subsystem dominates

Migration Rule

Do not start with six services because you predict future growth. Start with one codebase, draw module boundaries clearly, and split only after the boundary has shown up in production metrics, deploy friction, or team structure.

Good migrations usually peel off one thing at a time: search, billing, notifications, or media processing. Bad migrations split by technology layer or by guesswork.

  • Graphs — dependency graphs reveal coupling and blast radius
  • Message Queues — common glue once work becomes asynchronous across services