5 min read

Monolith vs Microservices

Split by team and deploy pain, not by noun. A modular monolith is usually the right first step.


The story

In 2018 Segment published an engineering post titled Goodbye Microservices. Segment sends customer data to a long list of third-party tools, which it calls destinations. Early on they gave each destination its own service, its own queue and its own repo. It sounded clean: one integration breaks, the rest carry on.

It grew to more than a hundred services. Each used a slightly different version of the shared libraries, because upgrading a hundred repos is nobody's sprint. Each needed its own scaling and alerting and its own on-call knowledge. A small team spent its time running the fleet instead of improving the product.

So they merged the destinations back into a single service in a single repo. Deploys and fixes got faster and operational load went down.

Five years later the Amazon Prime Video team wrote that moving one monitoring pipeline from distributed components into a single process cut its infrastructure cost by about 90%.

Neither post says microservices are bad. Both say the same thing: splitting a system has a price, and it's paid every day. The question is whether what you get back is worth that price for your team.


The idea: a function call becomes a network call

In a monolith, orders calling inventory is a function call. It takes nanoseconds, never gets lost, and runs inside one database transaction.

In microservices, the same call goes over the network, and the network can fail in every way it knows:

Every arrow you draw between services adds timeouts, retries, idempotency keys, a distributed transaction or saga, versioned APIs and distributed tracing. That's the bill.

What you get for it:

You getWorth it when…
Independent deploysTeams keep blocking each other's releases
Independent scalingOne part needs 50× the compute of the rest (video encoding vs account settings)
Fault isolationA crash in recommendations shouldn't take down checkout
Team autonomySeveral teams each own a part end to end
Different tech per partOne part really needs a different runtime (ML in Python, the rest in Node)

Look at the left column. Almost everything on it is about people and deploys, not performance. A three-person team gets almost none of it.


The middle option: the modular monolith

Most of what people want from microservices is clear boundaries. You can have those without the network.

The rules that make it work:

  • Modules call each other only through their public API, never by reaching into each other's internals.
  • Each module owns its tables. No module joins another module's tables directly.
  • Enforce both with lint rules or package boundaries, not good intentions.

If you later need to pull inventory out into its own service, the seam already exists. You swap an in-process call for a network call at one well-defined boundary instead of untangling a ball of mud. Shopify is the well-known example of running a very large business on a modular monolith.


When to split

Distributed monolith: services that must be deployed together, share a database, or call each other synchronously in long chains. You pay the full cost of microservices and get none of the benefits. It's the most common outcome of splitting too early.

How to extract safely: the strangler fig pattern. Put a router in front, move one route at a time to the new service, and delete the old code path only when traffic has fully moved.


Cheat sheet

SituationChoose
New product, 1–2 teamsModular monolith
Teams blocking each other's releasesExtract the part with the most release contention
One part needs very different scalingExtract that part only
Needs a different runtime (ML, video)Separate service for that part
Services share one databaseNot microservices yet: a distributed monolith
Long synchronous call chains (A→B→C→D)Latency and failure multiply. Use async events or merge them.
Migrating off a monolithStrangler fig: one route at a time behind a router
Rule of thumbAbout one service per team, not one per noun

Say it in the interview

"I'd start as a modular monolith: one deployable, strict module boundaries, each module owning its tables. That gives us clean seams without network calls between every part. I'd extract a service when a separate team owns it or it scales very differently, video transcoding being the obvious first candidate, using a strangler-fig route behind the gateway."


Go deeper