Should you use it?

Should you use microservices?

Almost certainly not yet. Start with a well-organised monolith and split out a service only when a specific part needs its own scaling, its own team, or its own release schedule.

The real question is how many teams you have

Microservices get sold as an architecture, but the thing they solve is people stepping on each other. The original case at the big shops was hundreds of engineers who could not all ship from one codebase without merge pain and coordinated releases. Splitting the system let each team own a service and deploy on its own schedule. That is a team-coordination win first, a technical one second.

So "should we use microservices?" is really "how many teams do we have, and are they colliding?" Five people have no coordination problem. They have a productivity problem, and microservices make it worse: now those five people run ten deployables, ten pipelines, and a network between things that used to be a function call.

Conway's law is the honest framing. Your architecture ends up mirroring your communication structure whether you plan it or not. Decide your team boundaries first, then let the service boundaries follow.

When microservices actually pay off

Independent deployability is the headline. When the payments team ships a fix at 2pm without waiting for the search team's release train, and without risking the search team's code, that is real velocity. Each service tests and rolls back on its own. With a hundred engineers, that independence is worth a lot.

You also get targeted scaling and fault isolation. If your image-processing path needs GPUs and runs hot while everything else idles, a separate service lets you scale and pay for exactly that, on the right hardware. And if recommendations falls over, a clean boundary keeps checkout working — the blast radius is contained instead of the whole app going dark.

Every one of these assumes you have already paid the entrance fee, and the fee is steep.

When to stay a monolith

If you are a small team, a monolith ships faster and is far easier to reason about. One deploy, one log stream, one place to set a breakpoint. The coordination cost microservices remove is a cost you do not have yet.

Skip the split when your domain boundaries are still moving, too. Carve services on lines you will redraw in six months and you pay twice: once to split, once to merge back. And if the real motive is the resume rather than a scaling or team problem, that is the clearest signal to wait.

What microservices actually cost

In a monolith, calling another module is a function call: nanoseconds, can't fail halfway, steppable in a debugger. Cross a service boundary and that call is a network round trip that can be slow, time out, retry, or partially succeed. Every boundary is a place the network can fail, and you have to design for it — timeouts, retries, circuit breakers.

Operationally the tax compounds. One deploy becomes ten. One log stream becomes ten, and a single request stitches across several, so you need distributed tracing just to answer "why was that slow?" You can no longer change a function and its caller in one commit, so API versioning becomes a real discipline. On-call gets harder, because the failure is usually in the interaction between three services, not inside one.

A monolith costs one unit of operational overhead; each service you carve off adds a meaningful slice on top. Small teams burn their whole productivity budget paying that bill and have nothing left for features.

The distributed monolith trap

The worst outcome is not the monolith. It is the distributed monolith: services split on paper but so chatty and coupled that you get all the network pain and none of the independence. You cannot deploy service A without B and C in lockstep. One user action fans out into eight synchronous hops. Change a shared field and four teams coordinate a release anyway.

The usual cause is splitting on the wrong lines and then sharing a database across services. The moment two services read and write the same table, you have recoupled everything you spent months separating, just with a network in the middle. The rule that prevents it: each service owns its data, full stop. Others ask through an API; they never reach into its tables.

Microservices vs a modular monolith

A modular monolith gives you most of the discipline of microservices with almost none of the operational cost. One deployable, but strict internal boundaries — clear modules, no reaching across them, each owning its own data even inside the same process. Calls stay in-process, so they are fast and debuggable, and your boundaries stay cheap to move while you are still learning where they really go.

Microservices add independent deploys, independent scaling, and hard fault isolation — and in exchange they add the network, the tracing, and the ten pipelines. The honest rule: stay a modular monolith until a specific module needs its own scaling, its own team, or its own fault domain. Then split that one. Most teams that thrive on microservices got there by peeling services off a healthy monolith, not by starting with twelve services and a wiki diagram.

How to adopt microservices without regret

Start with the modular monolith and keep it clean. When a module earns its way out — separate scaling, a separate team wanting its own cadence, or an isolated fault domain — extract that one. Because you kept it clean, the extraction is mechanical rather than archaeological.

Repeat only as the pressure appears. The expensive path is declaring everything a service on day one and waking up inside a distributed system you cannot debug. Let the pain pick the next service for you.

Quick reference

When it fits, when it doesn't

Reach for it when

  • Separate teams keep colliding in one codebase and need to ship on their own schedules.
  • One component has wildly different scaling or hardware needs from the rest (GPU jobs, heavy batch work).
  • You need to isolate a fault domain so one feature failing cannot take the whole product down.
  • A part of the system is stable enough to own a clear, rarely-changing contract.

Skip it when

  • You are a small team — a monolith ships faster and is far easier to reason about and debug.
  • Your domain boundaries are still moving; splitting too early freezes the wrong lines and you pay to redraw them.
  • You want microservices for the resume rather than a problem the architecture actually solves.

Common mistakes

  • Building a "distributed monolith" — services so chatty and coupled you get the network pain without the independence.
  • Sharing one database across services, which quietly recouples everything you tried to separate.
  • Underestimating the operational tax: tracing, deploys, versioning, and on-call all multiply.
Settle an argument?