When to Split a Monolith: Prove the Boundary Before Extracting

Test whether a service boundary will remove a measured constraint, compare in-process alternatives, and plan extraction with explicit data and recovery gates.

trigger="A monolith has a measured delivery, resource-isolation or operating constraint that may require an independently deployed capability." owner="The engineering leader owns the architecture decision; the proposed service owner accepts operation and the data owner authorizes changes in write authority." participants={["Engineering leader", "Domain architect", "Product owner", "Current and proposed service owners", "Database operator", "Security/release reviewer"]} prerequisites={["A measured constraint and a bounded candidate capability", "Dependency, transaction and ownership evidence", "A supported baseline and alternative interventions", "Capacity to operate and recover the proposed service"]} outputs={["A falsifiable extraction decision record", "A boundary and data-authority map", "A bounded pilot with acceptance and stop gates", "A recovery plan and a decision to retain, revise or stop extraction"]} doneWhen={["The selected option addresses the observed constraint", "The boundary preserves business and security invariants", "Operating costs and ownership are accepted", "The team can stop or recover at every authorized migration state"]} />

Split only when independence solves the observed problem

A monolith can be difficult to change, but deploying its modules separately does not automatically make them independent. Shared data ownership, synchronized releases and unclear responsibilities can survive the split, with network failures added.

Extraction can help when a capability needs a genuinely different release, resource, security or operating boundary. It can also fail to help when the real constraint is a slow query, unavailable reviewer, unstable test suite or poorly defined domain. User count, repository size and team size are not sufficient decision rules.

This playbook decides whether to extract a bounded capability and how to test that decision. Use the microservices migration playbook for the wider program and the strangler pattern runbook for detailed capability cutover.

1. State a hypothesis that can be wrong

The engineering leader names the constraint, the evidence and why a process boundary is expected to change it. Collect a representative window rather than choosing the worst release as the baseline.

Extraction hypothesis
  Capability and accountable owner:
  Observed constraint and evidence window:
  Why independent deployment or operation should help:
  Simpler alternatives and their test results:
  Expected improvement and acceptance measure:
  Reliability, security and cost guardrails:
  Evidence that would disprove the hypothesis:
  Pilot scope and decision date:

For example, a reporting workload may consume resources needed by interactive requests. The hypothesis could be that isolating its execution and resource budget protects the interactive service objective. If a separate worker in the current deployment model solves the contention, a new domain service may not be necessary.

For release friction, distinguish time actively coordinating code from waiting for a legitimate approval, customer window or shared specialist. Multiple contributors do not automatically imply harmful coupling. Trace what caused the delay and which part of it a separate service would remove.

Gate: the hypothesis predicts an observable change and a condition under which the team will decide not to extract. Do not use a universal coordination percentage as the trigger.

2. Compare interventions at the actual constraint

The architect and current service owner test the least disruptive plausible option. The smallest code change is not always the safest, but a distributed design needs a reason beyond fashion.

| Observed constraint | Option to test before or alongside extraction | When extraction may add useful independence | |---|---|---| | Conflicting edits and unclear responsibility | Explicit module interfaces, ownership and review paths | The capability also needs an independent release/operating boundary | | One workload exhausts resources | Profiling, query fixes, limits or a separately scheduled worker | Its resource lifecycle cannot be safely isolated in the current design | | Slow release validation | Test isolation, affected-check analysis and artifact reuse | Independent release evidence can be maintained without coordinated consumers | | Different security exposure | Least privilege, network controls and data minimization | A distinct trust boundary can be enforced and operated | | Shared schema changes block teams | Clear write ownership and compatible schema evolution | A coherent capability can own its data and external contract |

Feature flags separate activation from deployment; they do not make code independently deployable or undo persisted effects. Read replicas introduce freshness and routing choices, and a cache needs invalidation and access controls. These alternatives have costs too, so compare evidence rather than labeling every in-process option “cheap.”

Gate: the decision record explains why the selected option addresses the cause. If a smaller intervention meets the requirement, retain it and review only if the constraint returns.

3. Draw a boundary around behavior, data and ownership

The domain architect maps what the capability decides, what data it owns and what invariants must remain atomic or otherwise consistent. Include APIs, jobs, reports, direct SQL, support tools and external effects.

AWS's capability-decomposition guidance depends on domain understanding. Microsoft's boundary guidance asks teams to consider cohesion, deployment dependencies and data consistency. Neither substitutes a fixed list of services for the actual domain model.

Candidate boundary worksheet
  Business decisions and supported operations:
  Inputs, outputs and compatibility policy:
  Tables/records read and written:
  Authoritative writer for each record type:
  Transactions and invariants crossing the boundary:
  Synchronous dependencies and failure behavior:
  Events, retries, duplicates and ordering:
  External effects that cannot be undone:
  Security principal, access policy and data classification:
  Build, deploy, on-call and recovery owners:

A capability may need a read model containing data owned elsewhere. Define freshness, deletion and permission-change propagation before using it. Replacing an in-process join with a sequence of remote calls can increase latency and create new partial-failure states.

Authentication is not inherently a safe first extraction: many workflows depend on it, and errors can affect access across the product. Notifications and file operations can disclose information or produce irreversible external effects. Choose the first candidate from the dependency and risk map, not a generic “leaf service” list.

Gate: domain and data owners can explain each cross-boundary invariant. If the required atomic behavior cannot be preserved within accepted tradeoffs, redraw the boundary or keep the operation together.

4. Price the transition and the steady state separately

The platform owner and engineering lead estimate infrastructure, delivery and operating work. Finance reviews rates and cost treatment. There is no supported universal multiplier for infrastructure, debugging effort or a post-split slowdown.

| Cost view | Include | Verify with | |---|---|---| | Transition | Interface work, migration, duplicate operation, test environments and consumer changes | Bounded implementation estimates and a pilot | | Steady state | Compute, storage, network, identity, monitoring, support and maintenance | Workload tests, dated prices and an operating backlog | | Coordination | API evolution, incidents across owners and dependency changes | A release/recovery rehearsal | | Opportunity | Specific product work displaced by the transition | Product priorities and capacity scenarios | | Exit | Recombination, replacement or retirement of the service | Data export and compatibility design |

Avoid counting existing payroll as both new cash expenditure and an additional opportunity-cost amount. Make internal capacity consumption visible without claiming it will turn into cash savings.

The proposed owner must accept deployment, patching, incident response, recovery, documentation and consumer support. Kubernetes, a mesh or a dedicated team per service is not a universal prerequisite. The hosting model must meet the service's actual objectives and the team's operating capability.

Gate: an owner and a funded operating path exist beyond the migration project. A technically successful extraction with no sustainable owner is not ready.

5. Prove the interface inside the existing system

Where feasible, introduce an in-process interface before moving execution across a network. Keep behavior unchanged while callers adopt the interface. Enforce module boundaries using tooling supported by the actual language and repository; do not copy an unverified generic linter configuration.

Write contract and characterization tests, then classify differences with the domain owner. An existing bug is not a behavior to preserve without question. Add tests for access denial, invalid inputs, timeouts, retries and unknown outcomes.

"type": "flow", "title": "Extraction is a sequence of evidence gates", "steps": [ ], "caption": "The team can keep the internal module after the interface stage. A successful boundary does not require a network service unless the independence hypothesis is supported." }} />

An internal interface cannot prove network behavior. Before extraction, define timeouts, connection limits, retry budgets, identity propagation, contract compatibility and observability. Decide which calls are safe to retry and how to discover the outcome after a timeout.

Gate: current consumers use the intended contract, hidden direct access is understood, and the new failure boundary has a tested design.

6. Pilot one capability with explicit authority

The release owner creates a routing or application boundary that initially preserves the existing path. It must not become an untested bottleneck or single point of failure. Microsoft's strangler guidance describes incremental routing and transitional costs; suitability depends on being able to intercept the relevant operations.

Select a bounded cohort and preserve required affinity. Do not randomly split steps of one stateful operation across incompatible implementations. If comparing results in shadow mode, isolate writes and suppress external effects. A shadow payment, email or export must not reach a real recipient or provider.

Code movement and data separation need not follow one universal order. Choose the sequence that preserves known authority and compatibility. Shared storage during a transition is not automatically a failure, but direct cross-owner writes must not remain an unexamined permanent dependency.

Gate: pilot traffic has a clear stop owner, observable business outcomes and a safe response to failure.

7. Separate data only with reconciliation and rollback gates

The data owner maps every writer, including scheduled jobs and administrative tools. Do not rely on two best-effort application writes to keep stores synchronized. One can succeed while the other fails, and retries can reorder changes or resurrect deleted records.

Use an appropriate durable change mechanism. The transactional outbox pattern can connect a local commit to later publication, with idempotent consumers and reconciliation still required. Snapshot/backfill work needs a matching change position, resumable checkpoints and explicit treatment of updates and deletes.

| Migration state | Authority | Gate before advancing | Recovery boundary | |---|---|---|---| | New implementation under test | Existing writer remains authoritative | Contracts and isolated comparison pass | Remove the trial without losing production writes | | New store receiving a copy | Existing writer plus durable change capture | Backfill, lag and record/invariant reconciliation pass | Rebuild the copy while the authoritative source is intact | | Write cutover | Fence old writers; new writer takes authority | All entry points respect fencing and recovery is rehearsed | Old code is usable only if it understands and receives current data | | Legacy retirement | New authority accepted | Consumers, retention, recovery and reconciliation are closed | Restoration requires an explicit replay/rebuild plan |

After new authoritative writes, rollback may require reverse synchronization, transformation and reconciliation. If that path is not safe, the accepted recovery strategy may be containment and a forward fix. Keeping old tables does not make them current; dropping them is a separate, deliberate decision.

A distributed workflow may use local transactions and compensation, but compensation is not a database rollback. AWS's saga guidance discusses retry, idempotency, isolation and observability concerns. Determine which business actions can actually be compensated and how unresolved outcomes reach an operator. Do not assume all cross-service atomicity is impossible, or that a saga satisfies a strong-consistency requirement by default.

8. Exercise the failures before expanding

| Failure test | Expected behavior to establish | Decision if it fails | |---|---|---| | New service is slow or unavailable | Bounded caller waiting, load and retries | Hold extraction until failure does not cascade | | Response is lost after a committed action | Outcome lookup or safe idempotent retry | Do not retry an unknown external effect blindly | | Old and new consumer versions coexist | Supported contracts and data semantics remain valid | Keep compatibility or coordinate an explicit migration | | Change capture stops or reorders work | Detect lag, preserve replay and reject stale updates | Hold data cutover and repair/reconcile | | Old writer resumes after cutover | Fencing prevents conflicting authority | Stop writes if authority cannot be established | | Privilege or tenant context is forged | Server-side policy rejects the operation | Treat as a security blocker, not a tolerable mismatch | | Rollback is requested after new writes | Reconciliation or forward recovery follows the approved plan | Do not switch traffic to stale data |

The service and data owners attach results to the decision record. Include an operator who did not build the migration in the recovery rehearsal. A diagram and a successful happy-path request are insufficient evidence.

9. Run a two-week boundary validation before extraction

Treat the proposed service boundary as a hypothesis that can be tested while the capability still lives inside the monolith. Give one team temporary ownership of the relevant code path, data changes, alerts and support questions. Record every change that crosses the proposed boundary. Classify each crossing as a stable contract, a shared policy, a data dependency, a coordinated release, or an accidental shortcut.

During the validation window, ask the team to make one safe change using only the proposed contract. The exercise should expose whether terminology, authorization, transaction scope and failure ownership are actually understood. It also reveals whether the candidate can be operated independently or still relies on informal knowledge elsewhere in the system.

Create a boundary evidence pack with:

  • a context map showing callers, data owners and external effects;
  • the proposed API or event contract with compatibility rules;
  • a list of writes and invariants that still cross the boundary;
  • deployment, alert, recovery and support ownership;
  • baseline lead time, failure rate and operational effort;
  • the expected improvement and the date it will be measured; and
  • a signed decision to extract, revise the boundary, or keep the module in place.

Do not score the exercise by the number of dependencies discovered. Score it by whether each dependency has a deliberate owner and treatment. A shared identity policy may be appropriate. A shared writable table with undocumented invariants is not.

10. Define acceptance evidence before construction

The extraction is complete only when evidence supports the original hypothesis. Contract tests should cover supported consumer versions. Authorization tests should prove that tenant and object boundaries survive every entry point. Reconciliation should compare business facts, not just row counts. Load tests should include downstream limits and failure behavior. The on-call owner should be able to identify authority, contain a fault and recover without the original extraction team.

Set an observation period long enough to include representative releases and workload conditions. Record any confounders, such as a traffic reduction or unrelated database upgrade. If the target constraint does not improve, the honest result is that the hypothesis was not supported. That result prevents a wider, more expensive decomposition and is therefore useful.

Decide whether to retain, revise or stop

Repeat the baseline under comparable conditions. Did the intended constraint improve? Did new network or operational work erase the benefit? Can the owner release, diagnose and recover the capability independently without routine coordinated changes?

Retain the extraction when acceptance and guardrails hold. Revise the boundary if the desired independence requires excessive cross-service coordination. Stop further extraction when the hypothesis is not supported. Returning a capability to the monolith is possible only through a planned compatibility and data transition, not by deleting the service.

Do not infer that one successful extraction justifies decomposing the entire system. Some capabilities can remain together indefinitely.

"The decision names a measurable constraint and disconfirming evidence", "Alternatives were compared against the same outcome", "The candidate has a coherent contract, data ownership and operating owner", "Authentication, notifications and external effects were assessed by actual risk", "Transition and steady-state costs use explicit inputs, not universal multipliers", "The pilot tests network failure, access controls and mixed versions", "Data cutover uses durable changes, fencing and reconciliation", "Rollback conditions are valid after new authoritative writes", "Legacy retirement requires separate evidence and authorization", "The final decision can be retain, revise or stop without hiding the result" ]} />

This playbook does not promise lower costs or faster delivery, and it does not replace application-specific security or data review. Start with the boundary worksheet and one falsifiable hypothesis. System architecture design is the relevant scope when the team needs help testing that boundary before committing to extraction.