Skip to content

step 14 / 32 · 6 min

Monolith, services, and the honest comparison

How a system is divided into deployable pieces is one of the harder decisions to reverse, and it is frequently made for the wrong reasons.

Monolith

One deployable unit. All the code, one process, usually one database.

code
[  web | orders | payments | inventory  ]  ->  [ database ]

What it gives: a function call instead of a network hop, one transaction across everything, one thing to deploy, one place to debug, and a stack trace that crosses the whole request.

What it costs: everything deploys together, so one team's change blocks another's. Scaling means running more copies of everything, even the parts that are idle. Over time the boundaries blur unless someone defends them.

Services

Separate deployables, each owning its data.

code
[ web ] -> [ orders ] -> [ orders db ]
        -> [ payments ] -> [ payments db ]

What it gives: independent deployment, independent scaling, a fault contained to one service, and teams that can move without coordinating.

What it costs, and this is usually underestimated:

  • a function call becomes a network call that can fail, time out or arrive twice
  • a transaction across two services does not exist; you need sagas and compensation
  • a request spans several services, so debugging needs distributed tracing
  • local development means running several things, or mocking them
  • every service needs deployment, monitoring, alerting and on call
MonolithServices
Deployall togetherindependently
Transactionsfreedistributed, or given up
Debuggingone stack tracetracing across services
Operational loadone systemone per service
Team independencelowhigh

The honest guidance

Start with a monolith, with clear internal boundaries.

The reason is not that services are bad. It is that at the start you do not yet know where the boundaries are, and a boundary drawn in the wrong place is far more expensive to move once it is a network interface. Inside one codebase it is a refactor.

The signal to split is organisational more often than technical: several teams blocking each other on one deployment pipeline. A single team running twelve services has taken on the costs and none of the benefit.

The middle ground

A modular monolith enforces boundaries inside one deployable: modules that communicate through defined interfaces and do not read each other's tables. It gets most of the design benefit with none of the distributed systems cost, and it makes extracting a service later mechanical rather than archaeological.

Monolith, services, and the honest comparison