Distributed Systems & Enterprise ResiliencePlaybook3 min readUpdated September 2026

Deciding Where to Draw Service Boundaries, and Where Not To

The microservices-versus-monolith debate is usually framed as a single, company-wide choice, which is the wrong scale to make the decision at. The real question is narrower and gets asked over and over: does this specific boundary, between these two specific pieces of the system, earn the operational cost of a network call and a separate deployment?

This guide walks through how to answer that question for one boundary at a time, instead of picking a company-wide architecture and forcing every piece of the system into it.

What a Service Boundary Actually Costs You

Every service you split off adds a network call where there was a function call, a separate deployment pipeline, its own on-call burden, and a new way for a partial failure to happen: the service being up but slow, or up but returning stale data. None of that is free, and all of it is easy to underestimate when the split looks clean on a whiteboard.

That cost isn't a reason to avoid splitting anything, it's a reason to make sure each specific split is paying for itself, rather than assuming services are simply the more modern default.

Where a Split Actually Pays Off

A boundary earns its cost when the two sides genuinely need to scale, deploy, or fail independently, a background job processor that needs to scale wildly during peak load while your main API stays flat, or a component with a fundamentally different reliability requirement than the rest of the system.

A boundary drawn along team lines, so each team can own its own service, is a legitimate reason too, but only once the team is large enough that shared ownership of a monolith is itself the bottleneck, not before.

Where a Split Just Adds Overhead

Splitting two pieces of logic that always deploy together, always scale together, and are maintained by the same one or two engineers usually adds operational cost without buying any of the independence that's supposed to justify it. You get the network call and the separate deployment pipeline, without the scaling or ownership benefit that would make either worth it.

This is the most common overcorrection: teams that read about the benefits of services and split along technical layers, like a separate "validation service" or "formatting service," instead of along real independence boundaries.

Decomposition and Your Deploy Frequency

How your services are split affects your deploy frequency: a team releasing on demand can keep changes small and contained to one service at a time, while a team stuck at monthly releases, often because too many services must move in lockstep, ends up bundling changes across boundaries that were supposed to be independent, which defeats much of the point of splitting them in the first place1.

If your services can't deploy independently of each other in practice, that's a sign the boundary was drawn in the wrong place, not just a coordination problem to work around. Two services that must always ship in the same pull request or the same release window aren't really two services operationally, whatever the deployment diagrams say.

A Safer Way to Test a Boundary Before Committing

Before extracting a service, enforce the boundary inside the monolith first: a clean internal interface, no direct database access across the boundary, no shared internal state. If that internal boundary holds up cleanly for a few months, extracting it into an actual service is mostly mechanical.

If the internal boundary keeps getting violated, with shortcuts and direct reaches across it under deadline pressure, that's useful information too: it usually means the boundary wasn't a natural one, and splitting it into a separate service would have just made those violations more expensive to work around.

This approach also removes most of the risk of getting it wrong. Reverting an internal interface that didn't work out is a code change; reverting an already-extracted service, with its own deployment pipeline and its own on-call rotation, is a much bigger undertaking that teams tend to avoid even after they've realized the split wasn't worth it.

Follow this sequence before extracting a service:

  1. Define a clean internal interface for the boundary inside the monolith.
  2. Block direct database access across the boundary so each side owns its own data.
  3. Remove any shared internal state between the two sides.
  4. Watch whether the boundary holds for a few months, and treat repeated shortcuts as a sign the split may not pay for itself.
  5. Extract the service only when the boundary holds and you can name a concrete reason it needs to scale, deploy, or fail independently.
Executive Capability Standard

What Good Looks Like

Good service boundary practice means each split can point to a specific, concrete reason, independent scaling, independent deployment, or independent team ownership, rather than being drawn by default along whatever technical layers looked clean on a diagram.

Building The Capability (5-Stage Skill Ladder)

1. Learn:Read through your current service map and, for each boundary, write down the specific reason it exists, since a boundary nobody can justify anymore is a candidate to reconsider.
2. Do Manually:Enforce a proposed boundary inside the monolith first, with a clean interface and no shared state, before committing to the cost of extracting an actual service.
3. Delegate:Give a senior engineer or architecture group ownership of reviewing proposed new service boundaries against the independence test before they're built.
4. Automate:Add a lint or CI check that flags direct cross-boundary database access within the monolith, so a boundary you're testing internally doesn't quietly get violated under deadline pressure.
5. Buy:Bring in outside architecture review for a genuinely large, cross-cutting decomposition decision, not for routine boundary calls your own team can reason through.

How to Get Started

Frequently Asked Questions

How do we decide if a piece of our system should become its own service?

Ask whether it genuinely needs to scale, deploy, or fail independently from the rest of the system. If the answer is yes for a specific, concrete reason, the boundary likely earns its operational cost. If the two pieces always deploy and scale together, splitting them usually just adds overhead without a matching benefit.

Is it a mistake to split services along technical layers instead of business boundaries?

Usually, yes. A separate "validation service" or "formatting service" split along a technical layer rarely gains independent scaling or deployment, since it still has to change in lockstep with whatever calls it. Boundaries drawn around genuine independence, in scaling, deployment, or team ownership, tend to hold up better.

How can we test a service boundary before actually extracting it?

Enforce it inside the monolith first: a clean internal interface, no direct cross-boundary database access, no shared internal state. If that holds up cleanly for a few months, extracting it into a real service is mostly mechanical. If it keeps getting violated, that's a sign the boundary wasn't a natural one.

Does splitting into microservices automatically improve our deploy frequency?

Only if the resulting services can actually deploy independently of each other. If changes still have to move across several services in lockstep because the boundaries weren't drawn cleanly, you've taken on the operational cost of services without gaining the independent deploy cadence that's supposed to justify it.

Sources

Where we quote a benchmark, we show its source. Other figures in this guide are estimates or general guidance, so check them against your own numbers.

  1. Deployment frequency by DORA performance cluster (max days between deploys). DORA Accelerate State of DevOps 2024 (Google Cloud), cluster table via Octopus Deploy analysis, 2024.

Related Guides