# Boundary-First Modernisation Playbook

**An opinionated, operational guide to selecting migration patterns, minimising disruption, and retiring legacy dependencies**

> **Citation convention:** Sources are cited as simple inline numbers, such as `modernise incrementally[1]`. Their corresponding URLs appear under **References** at the end of this document. No proprietary citation syntax or Markdown footnotes are used.

## Executive summary

The central recommendation of this playbook is deliberately opinionated: **default to incremental, boundary-first modernisation; use the strangler pattern as the primary migration strategy where a viable boundary and seam exist; and treat most of the other named patterns as techniques that support, constrain, or occasionally replace it rather than equivalent alternatives.** The original strangler concept was created as an alternative to high-risk cut-over rewrites: introduce new capability around the existing system, divert progressively more behaviour to it, and retire the old implementation only after the replacement has proved itself.[1][2][3]

The wrong question is:

> “Should we strangler this application, lift-and-shift it, or rewrite it?”

The better question is:

> **“What is the smallest business-and-data boundary that can migrate independently, and what combination of migration, compatibility and release techniques makes moving that boundary safe?”**

A modernisation programme operates at several layers simultaneously:

| Layer | Primary question | Typical technique |
|---|---|---|
| **Portfolio strategy** | Should this workload be changed at all? | Retain, retire, rehost, replace, rebuild, refactor |
| **Decomposition strategy** | How do we move capability out of the existing system? | **Strangler by default**, selective rewrite, branch-by-abstraction |
| **Boundary protection** | How does the new model coexist with legacy semantics? | Anti-corruption layer, facade, adapter |
| **Data evolution** | How do old and new representations coexist? | Expand–migrate–contract, replication, backfill, change capture |
| **Correctness assurance** | How do we prove equivalence before taking ownership? | Parallel run, shadow traffic, reconciliation |
| **Release control** | How do we expose the change safely? | Feature toggles, cohorts, canary |
| **Failure control** | How do we get back safely? | Routing reversal, compatibility window, restore/replay, compensating action |

**Feature toggles, canarying, facades and parallel running are generally not alternatives to strangling a system.** They are mechanisms *inside* a strangler migration. Canarying tests a limited release against a control; feature flags separate deployment from exposure; parallel change allows a breaking interface or schema to evolve without requiring every consumer to change at once.[5][6][7][26]

### The six executive biases

**1. Bias towards business boundaries, not technical layers.** Candidate boundaries should correspond to cohesive business concepts, ownership and transactions. Bounded-context thinking and research into service decomposition favour business-oriented seams over arbitrary divisions of classes, packages or tables.[8][9][10]

**2. Bias towards one authoritative writer per piece of business state.** During migration, duplicated data is often necessary; duplicated authority usually is not. Distributed operations require conscious consistency and compensation decisions.[8][17]

**3. Bias towards reversible changes before elegant end-state architecture.** The transitional architecture can be inefficient because both old and new coexist. That buys observability, rollback and learning.[2]

**4. Bias towards migration by vertical slice.** Move a user-visible capability, its contract, state responsibility, operational ownership and rollback mechanism together. Avoid a modern front end sitting over the old shared database indefinitely, unless explicitly time-boxed.

**5. Bias towards proving the seam before scaling the programme.** The first boundary should reveal integration, data, deployment, observability and governance problems, but be survivable if those problems occur.

**6. Bias against calendar-driven decommissioning.** Retire a legacy component only when traffic, consumers, write authority, recovery paths and compliance obligations have demonstrably moved.

The end-state goal is not any fashionable deployment topology. It is **independent changeability**: teams can modify, deploy, operate and eventually replace a capability without coordinating an estate-wide release. The relationship between organisational communication structure and system design is well established, and empirical delivery research finds platform and cross-functional team structures to be recurring approaches to supporting this autonomy.[14][15]

### Core migration flow

```mermaid
flowchart LR
    U[Users / callers] --> R[Routing seam]
    R -->|Legacy capability| L[Legacy system]
    R -->|Migrated capability| N[New boundary]
    L --> LD[(Legacy-owned data)]
    N --> ND[(Boundary-owned data)]
    LD -. replication / backfill .-> ND
    N --> A[Temporary adapter]
    A -. legacy dependency .-> L
    M[Metrics + reconciliation] --> L
    M --> N
    N --> C[Increase traffic after proof]
    C --> D[Remove legacy dependency]
```

**Traffic migration and data-authority migration are separate decisions.** Routing 100% of requests to a new service while the old system still owns every write is not completion. Copying all data while applications still depend on old interfaces is not completion either.

---

## 1. The problem modernisation is actually solving

### 1.1 The failure mode is coupling, not age

A legacy system is problematic when a small change requires understanding, testing, deploying or coordinating many unrelated areas. Age alone does not cause this condition. A mature, modular system may be simpler to change than a new distributed system with poor boundaries.

Research on monolith-to-service migration treats assessment and decomposition as first-order questions, rather than assuming extraction itself is the answer. A quality-driven migration study distinguishes transformation strategy from implementation and evaluates the outcome sought.[13]

**Modernisation is justified when the cost or risk of change has become structurally higher than the value of leaving the system alone.**

| Signal | What it suggests | Modernisation implication |
|---|---|---|
| Small features require estate-wide releases | Deployment coupling | Find deployable seams |
| One schema is touched by unrelated domains | Unclear data ownership | Establish ownership before extraction |
| Change requires multiple teams to coordinate | Organisational coupling | Align teams with boundaries |
| Regional rollout requires application forks | Policy mixed with core logic | Separate placement/policy boundary |
| Scaling one workload means scaling all | Runtime coupling | Isolate capacity-sensitive capability |
| Rollback restores an entire database | State coupling | Introduce compatibility/recovery windows |
| Production behaviour is poorly understood | Observability deficit | Instrument before decomposing |
| New implementation must copy obscure quirks | Behavioural coupling | Shadow and compare before cutover |
| Consumers query shared tables directly | Missing contracts | Introduce explicit contracts |
| Temporary migration bridges become permanent | Missing ownership/end condition | Give each bridge a deletion gate |

The worst programmes optimise for *destination technology* instead of reducing these forms of coupling.

### 1.2 What “boundary-first” means

A credible boundary aligns four things:

1. **Business semantics**: one coherent concept or business capability.
2. **State**: data needed to enforce the capability's invariants.
3. **Change cadence**: the capability can evolve without estate-wide synchronous releases.
4. **Ownership**: a single team is accountable for behaviour in production.

Domain-driven bounded contexts provide the semantic basis, but recent work also measures whether proposed decompositions violate transactional data ownership—because splitting packages neatly can still split invariants badly.[9][12]

> **If a proposed boundary cannot own its business rules and the data required to enforce them without routinely participating in synchronous distributed transactions, it is probably not yet a good extraction boundary.**

A bounded context need not be a separately deployed service. Semantic boundaries and deployment topology are different decisions.[8]

### 1.3 The unit of modernisation is a capability, not a table

Do not assume a customer table becomes a customer service, an address table an address service and a preference table a preference service. That can fragment invariants and convert local joins into network dependencies.

Start with business decisions that must remain atomic. If an operation such as order approval requires inventory reservation, fraud decision, account status and pricing, determine what genuinely requires atomic consistency versus explicit coordination.

Keep state required for one invariant together where practical. Across boundaries, define workflows, events and compensating operations rather than hiding distributed transactions inside an apparently simple API.[8]

### 1.4 Transitional architecture is intentional

During migration you may run two implementations, two schemas, two read paths, replicated data, adapters, routers and reconciliation jobs. That is not architectural failure. Parallel change explicitly relies on old and new representations coexisting during **expand → migrate → contract**.[5][25]

What is failure is making transitional components permanent without owner or exit condition.

**Every transitional artefact needs: owner + purpose + observability + removal condition + latest review date.**

---

## 2. Choosing the migration pattern

### 2.1 The default pattern-selection reference

| Pattern | Role | Use when | Avoid when | Default bias |
|---|---|---|---|---|
| **Strangler** | Decomposition/migration strategy | System must remain live; capability is isolatable; business keeps changing | No viable interception seam and coexistence is riskier than cutover | **Default if a real boundary exists** |
| **Modular-monolith refactor** | Structural improvement in place | Business boundaries need improvement but distributed deployment adds little value | Scaling/release isolation is a proven bottleneck | **Prefer to premature extraction** |
| **Branch-by-abstraction** | Replace an internal implementation | Functionality is buried inside a process; external interception is unnatural | Interface is so broad it merely mirrors the old subsystem | **Default for internal components** |
| **Big-bang rewrite** | Bounded replacement | Small known system; controlled consumers; downtime acceptable | Critical, evolving, undocumented, state-heavy system | **Rare exception** |
| **Lift-and-shift** | Tactical infrastructure relocation | Support or hosting deadline precedes feasible refactor | Claimed as architectural modernisation | **Tactical only** |
| **Anti-corruption layer** | Semantic isolation | Legacy and target models disagree | Pure protocol pass-through with no semantic mismatch | **Use at dirty boundaries** |
| **Facade/adapter** | Interception seam | Callers need a stable contract while implementation moves | Adds indirection without migration purpose | **Common enabler** |
| **Parallel run/shadow** | Correctness validation | Wrong output is expensive; side effects can be suppressed | Duplicate execution could trigger irreversible actions | **Default for consequential logic** |
| **Feature toggle** | Exposure control | Old/new behaviour can coexist with quick disable | State change makes switching back unsafe | **Standard release capability** |
| **Canary** | Traffic progression | Cohorts and metrics are meaningful | Failures are delayed or irreversible | **Default rollout technique** |
| **Parallel change** | API/schema evolution | Consumers cannot move simultaneously | No feasible compatibility interval | **Default for breaking contracts** |
| **Backfill + change capture** | Data transition | Ongoing source writes and large datasets make stop-the-world copy impossible | Source changes cannot be reliably captured or ordered | **Use with reconciliation** |
| **Retain/retire/replace** | Portfolio disposition | Capability is stable, redundant, or better purchased | Custom business advantage would be lost | **Always evaluate before rebuilding** |

The strangler pattern reduces replacement risk by gradual migration; branch-by-abstraction achieves a similar outcome for internals that cannot be intercepted naturally at the application perimeter.[1][4]

### 2.2 Decision criteria

Score each candidate boundary **1 (low) to 5 (high)**. The scale is a discussion tool, not a mathematically validated index.

| Criterion | 1 | 3 | 5 | Implication |
|---|---|---|---|---|
| Business consequence | Internal convenience | Important workflow | Core transaction, safety, identity | Higher → progressive cutover and verification |
| Behavioural uncertainty | Strong contracts | Partial documentation | Undocumented edge cases | Higher → shadow/parallel evidence |
| Data coupling | Isolated state | Some shared joins | Shared write-heavy schema | Higher → ownership work first |
| Transaction coupling | Local invariants | Few cross-domain workflows | Many distributed invariants | Higher → revise boundary |
| Downtime intolerance | Hours possible | Minutes | Near zero | Higher → compatibility-first |
| Rollback difficulty | Re-deploy | Data repair | Irreversible business outcome | Higher → delay state cutover |
| Regional control | Minimal | Regional policy | Residency and operational autonomy | Higher → regional execution design |
| Latency sensitivity | Loose | Moderate | Hard real-time path | Higher → avoid synchronous hops |
| Hidden dependencies | Known few | Several | Many consumers/side channels | Higher → discovery first |
| Team ownership | One team | Shared | Many sign-offs | Higher → organisational work first |
| Business change rate | Stable | Moderate | Rapid | Higher → avoid long rewrite |

**Choose migration strategy primarily on irreversibility, not coding estimate.** An easy rewrite that is hard to validate can be the riskiest option.

### 2.3 Practical decision tree

```mermaid
flowchart TD
    A[Candidate capability] --> B{Can old and new coexist?}
    B -->|Yes| C{Stable external seam?}
    C -->|Yes| S[Strangler migration]
    C -->|No| I{Internal abstraction possible?}
    I -->|Yes| BA[Branch by abstraction]
    I -->|No| R[Refactor in place to create seam]
    B -->|No| D{Small, understood and downtime acceptable?}
    D -->|Yes| BB[Consider bounded replacement]
    D -->|No| E{Immediate infrastructure exit?}
    E -->|Yes| LS[Rehost then modernise]
    E -->|No| F[Design a safe coexistence strategy first]
    S --> G{Different domain semantics?}
    BA --> G
    R --> G
    G -->|Yes| ACL[Anti-corruption layer]
    G -->|No| H{High correctness consequence?}
    ACL --> H
    H -->|Yes| P[Parallel run or shadow comparison]
    H -->|No| J{Schema or contract breaking?}
    P --> J
    J -->|Yes| PC[Expand migrate contract]
    J -->|No| CA[Canary or cohort exposure]
    PC --> CA
    CA --> W[Separate write-authority decision]
    W --> Z[Delete obsolete paths]
```

### 2.4 When strangler should be the default

Use it where the old system must operate throughout, requirements continue changing, some capabilities are independently isolatable, behaviour includes undocumented edge cases, and progressive movement can materially reduce cutover risk. Its original rationale is precisely incremental delivery and replacing parts without wagering the business on one release.[1][2]

**Do not call it a strangler migration if you cannot name what will ultimately be deleted.**

### 2.5 When *not* to strangle

**Small disposable application.** Controlled users, little state, a short cutover window: direct replacement may be simpler.

**System being retired.** Maintain only what is necessary until shutdown; do not build a new architecture for a disappearing capability.

**Immediate infrastructure deadline.** Rehosting may be the safer first move. Fund subsequent architectural change separately.

**Buried internal library.** Use branch-by-abstraction to replace implementation without inventing a network boundary.[4]

**Highly transactional cohesive core.** Refactor to a modular monolith if a service split would create a synchronous distributed transaction for every business command.

**Hard regional partition.** Operate an independent regional boundary if shared global runtime or control-plane dependencies are disallowed.

### 2.6 What almost never works

Avoid a multi-year rewrite where the old system keeps acquiring features, replacement runs no production traffic until the end, data migration is deferred, acceptance is one final gate, and rollback is merely “restore backup”. That accumulates behavioural and state uncertainty until the moment of highest blast radius.

---
## 3. Finding the right boundaries

### 3.1 Use four independent views

No one decomposition technique is sufficient. Static dependencies, runtime traces, domain language and data ownership reveal different forms of coupling. Research combining static/dynamic analysis with bounded-context reasoning supports a multi-view approach.[9][10][12]

For every candidate domain, produce four maps:

**Business map:** capabilities, domain language, decisions, owners, upstream and downstream actors.

**Runtime map:** top workflows through APIs, queues, jobs, stored procedures, files and data access.

**State map:** authoritative stores, write paths, transactional invariants, classification, retention and replication.

**Change map:** components that change together, correlated releases, teams that must coordinate.

A good extraction boundary shows evidence of alignment across all four—not just a neat domain diagram.

### 3.2 Boundary scorecard

| Question | Healthy signal | Warning signal |
|---|---|---|
| Does it have a business name? | Business vocabulary describes it | Named after a database/table/layer |
| Who owns the outcome? | One accountable team | Ownership fragmented |
| What state does it own? | Explicit authoritative dataset | Shared mutable tables |
| Which invariants are local? | Most critical rules local | Frequent distributed transactions |
| Who consumes it? | Known API/event contracts | Direct database access |
| Can it fail independently? | Degraded mode understood | Failure cascades everywhere |
| Can it scale independently? | Distinct capacity profile | Shared process bottlenecks only |
| Can it deploy independently? | Contract compatibility | Synchronous releases required |
| Can it roll back? | Old path state-compatible | New path destroys old state |
| Can it be observed? | Boundary-level SLOs/traces | Only whole-system dashboards |

### 3.3 Start from invariants

Ask in a domain workshop:

> **“What must remain true immediately after this business operation completes?”**

Typical answers:

- An available balance cannot cross a configured limit.
- A username must be unique.
- An entitlement cannot activate without an approved policy.
- An order cannot receive two conflicting final payment outcomes.

These statements expose the required atomic state boundary. Do not begin by asking how many services the target diagram should contain.

### 3.4 Treat contracts as ownership agreements

Every boundary contract should define:

- Command and query semantics.
- Idempotency keys, scope and retention.
- Consistency, ordering and read-your-writes expectations.
- Timeouts, retryability, error semantics and conflict responses.
- Compatibility/versioning policy.
- Ownership of identifiers and their uniqueness.
- Data-freshness guarantees.
- Security classification, authorisation and placement.

Consumers should not need to understand internal storage.

### 3.5 Data ownership guardrails

**One authoritative writer.** Copies are allowed; ambiguity over business authority is not.

**Read replication is usually safer than shared write authority.** It can reduce hard coupling while retaining a clear origin.

**Cross-boundary writes require an explicit protocol.** Use durable workflows and compensations where atomic multi-system commits are not available or justified.[8][17]

**Reconciliation is mandatory for consequential data.** Counts alone are inadequate; validate business invariants, monetary aggregates, identity/entitlement decisions and record-level equivalence as risk requires.

**Additive schema migration comes first.** Preserve compatibility through expand, migrate and contract.[5][25]

### 3.6 Data-authority migration sequence

A common progression is:

**Copy → catch up → compare → shadow → switch reads → switch writes → observe → disable old writer → contract.**

This is an operating sequence, not a claim that every system supports the same replication primitive. Live data migration literature describes initial copying paired with log-based change capture to bring new representations up to date.[16]

Avoid naive application dual writes. When two independent writes are sent to separate systems, one can commit while the other fails, producing divergence. Durable propagation must address that asymmetry with recoverable transactions, outbox/log-based mechanisms, replay, deduplication and reconciliation.[17]

### 3.7 Design the data transfer as an explicit state machine

```mermaid
stateDiagram-v2
    [*] --> Inventory
    Inventory --> Backfilling
    Backfilling --> CatchingUp
    CatchingUp --> Reconciling
    Reconciling --> ShadowReads: Consistent snapshot
    ShadowReads --> CanaryReads: Behavioural checks pass
    CanaryReads --> WriteTransferReady: SLOs pass
    WriteTransferReady --> NewAuthority: Explicit approval
    NewAuthority --> Stabilisation
    Stabilisation --> Contracted: Old paths provably unused
    Backfilling --> Repair: Data mismatch
    CatchingUp --> Repair: Excess lag
    Reconciling --> Repair: Invariant breach
    ShadowReads --> Repair: Semantic mismatch
    CanaryReads --> Repair: Regression
    Repair --> CatchingUp
```

Use a *separate* decision gate for switching the authoritative writer. Changing which service answers a GET is not equivalent to changing which durable system commits business state.

### 3.8 Last-mile and regulated regions

The applicable jurisdiction, sector and classes of data must be determined for each programme. This section is architectural guidance, not legal advice.

Distinguish:

- **Residency:** where data is stored.
- **Processing locality:** where computation occurs.
- **Control-plane locality:** where administration/control operations originate.
- **Key sovereignty:** who controls the ability to decrypt.
- **Operational sovereignty:** whether a region can function without external control-plane or data-plane dependence.

These are different questions. In jurisdictions subject to cross-border personal-data transfer rules, location and transfers can have specific legal consequences and supplementary measures may be required.[18][19]

| Constraint | Preferred boundary arrangement |
|---|---|
| Data local, compute may be global | Local authoritative store; export only approved derived data |
| Data and processing local | Entire logical capability deployed regionally |
| Shared global identity, local sensitive profile | Global opaque identifier; local sensitive profile |
| Cross-region writes prohibited | Region-owned aggregate; approved asynchronous summaries |
| Region may disconnect | Local write authority and specified synchronisation policy |
| Certain global data prohibited locally | Approved tokenised/derived representation |
| Global dependency unavailable | Read-only or constrained-operation degraded mode |
| New target platform unapproved in one region | Bounded legacy regional implementation behind common contract |

> **Regulatory asymmetry should become a placement policy around stable domain contracts, not a permanent fork of business logic.**

A last-mile region does not have to block every other region. Preserve a compatible legacy island where necessary, with an independent replacement path and compliance gate.

Define the degraded-mode contract *before* migrating:

1. Which reads remain available?
2. Which writes remain permitted?
3. How stale may replicated state become?
4. What is durably queued locally?
5. What must stop rather than violate a control?
6. Who declares and exits degraded mode?

Contingency guidance emphasises essential-function identification, recovery priorities, alternative processing and regular testing.[20]

---

## 4. Pattern runbooks

### 4.1 Strangler migration

**Use for:** live migration of isolatable business capabilities.

**Preconditions:** a candidate boundary, an interception seam, measurable baseline, mapped consumers, known data authority and reversible routing.

**Illustrative planning horizon:** a first bounded production slice may take 6–12 weeks when foundations exist. This is *not* an industry benchmark. Shared-schema extraction, compliance approval or weak delivery automation can dominate.

**Execution:**

1. **Baseline.** Record request volume, P50/P95/P99 latency, errors, important business outcomes, toil and known exception types.
2. **Establish seam.** Introduce a router, facade or gateway. Send 100% traffic through it to legacy initially. Prove the seam itself changes nothing.
3. **Isolate domain semantics.** Define target contract and model. Add an anti-corruption layer if legacy terminology would contaminate it.
4. **Document authority by phase.** State which store owns each aggregate, even when copies exist.
5. **Backfill.** Populate target state; capture subsequent changes with repeatable ordering and replay.
6. **Reconcile.** Compare record state and business invariants, not merely counts.
7. **Shadow.** Execute the new path without externally visible side effects. Compare results.
8. **Canary reads.** Move internal or low-risk cohorts; observe and classify mismatches.
9. **Transfer write authority.** Approve separately; test idempotency, replay, conflicts and restoration/forward repair.
10. **Expand traffic.** Illustrative cohorts: 1% → 5% → 20% → 50% → 100%, or domain-shaped cohorts.
11. **Hold.** Cover meaningful traffic peaks and complete business cycles.
12. **Contract.** Remove old callers, old writer, replication, compatibility logic and obsolete structures.

**Test:** contract compatibility, invariant tests, representative traffic replay, failure injection, load, resilience, regional controls.

**Watch:** business-success rate, semantic mismatch, latency, error-budget burn, replication lag, backlog age, divergence and residual legacy calls.

**Rollback:** reverse reads/routes while data paths are compatible. Once new writes are authoritative, rollback must be a documented reverse-sync or forward-repair operation; a feature flag alone cannot undo state.

This incremental approach is the main advantage of the strangler: migration delivers and validates parts before complete replacement.[2][3]

### 4.2 Anti-corruption layer

**Use for:** legacy and target domains with materially different semantics, vocabulary or invariants. The layer translates the *meaning* of interactions, not simply the data format.[11][27]

**Runbook:** define the target model first; catalogue foreign concepts; build translation at the boundary; test captured historical edge cases; expose unknown fields and failed mappings; migrate consumers through the layer; remove obsolete translations after dependency retirement.

**Watch:** unmapped values, translation errors, fallback counts, semantic discrepancies and old-system call volume.

**Rollback:** redirect the caller while underlying business state is compatible.

**Pitfall:** letting the layer become an additional business engine. Translation is its job; new business policy belongs inside the owned domain.

### 4.3 Branch-by-abstraction / facade / adapter

**Use for:** an internal framework, library, subsystem or state-access component buried inside an application when external traffic interception is impractical. Branch-by-abstraction enables large-scale structural change without keeping a long-running unreleasable development branch.[4]

**Runbook:** introduce the smallest stable interface; put the existing implementation behind it; migrate all callers; detect and remove bypasses; implement the new backend behind the same contract; switch progressively; measure; delete the old implementation.

**Test:** contracts, concurrency behaviour, unusual errors, performance, resource and lifecycle semantics.

**Watch:** percentage of caller paths through abstraction, old/new implementation selection, remaining bypasses.

**Rollback:** rebind to old implementation if state contracts permit.

**Illustrative horizon:** 2–8 weeks for a bounded subsystem; much longer for multi-team caller migration.

**Pitfall:** creating an interface that copies every implementation quirk instead of expressing what consumers actually need.

### 4.4 Refactor a modular monolith rather than extract

**Use for:** a highly cohesive transactional core in which internal boundaries are poor but separate processes would add expensive network/consistency failure modes.

**Runbook:** identify invariants and coupling; create internal modules with explicit interfaces; enforce module import and database access rules; route callers through module APIs; remove cross-module mutable access; add module-level tests; measure change coupling; defer physical extraction until there is evidence it is useful.

**Go/no-go for service extraction:** extract only when at least one benefit—independent scaling, independent release, differentiated availability, regional placement or autonomous ownership—exceeds the operational complexity introduced.

**Watch:** cross-module dependency violations, shared-table writers, coordinated releases, incident blast radius.

**Rollback:** revert module-level bindings/release while preserving schema compatibility.

**Pitfall:** substituting “number of services” for “independent changeability”.

### 4.5 Parallel run / shadow execution

**Use for:** correctness-critical logic such as eligibility, account restrictions, pricing, identity, settlement calculations, fraud decisions and entitlements.

**Runbook:** capture production-representative inputs; execute old and new; suppress new-path side effects; normalise nondeterminism; compare outputs by business class; classify differences into bug, intended semantic change, stale input or permitted nondeterminism; resolve consequential differences; then canary.

**Watch:** mismatch rate *by business impact*, missing-comparison rate, version skew, stale inputs, latency and memory impact.

**Rollback:** continue serving the old result while the new path is shadow-only.

**Illustrative horizon:** 2–6 weeks after dual execution is ready, or a full business cycle where necessary.

**Pitfall:** an aggregate 99.9% match rate may mask all high-value transactions. Treat classes separately.

### 4.6 Feature toggles

Feature toggles decouple deployment from release and permit controlled cohort exposure; abandoned flags also create configuration and testing complexity.[6]

**Runbook:** assign owner and expiry/removal criterion; deploy code with new path off; test realistic production states; enable internally; then expand by cohort; monitor; remove flag once old code is retired.

**Watch:** exposure by cohort, errors and business outcomes by cohort, flag age and unknown configurations.

**Rollback:** disable only while underlying state remains compatible.

**Pitfall:** assuming toggle-off is safe after the new path has written non-backward-compatible state.

### 4.7 Canary releases

A canary exposes a limited population to a change and evaluates it against a suitable control group before broader deployment. Real-world cohorts must be chosen for comparable traffic and failure blast radius, not just a random percentage.[7][26]

**Runbook:** define control and canary cohorts; pre-approve pass/fail criteria; deploy; inspect availability, latency and business outcomes; expand stepwise; automatically halt or revert on limits; complete after the observation window.

**Watch:** latency, errors, saturation, decision correctness and success rates against control.

**Rollback:** reverse routing to control if data semantics allow.

**Pitfall:** 1% traffic can still be 100% of a small critical tenant, region or rare transaction class.

### 4.8 Parallel change / expand–migrate–contract

**Use for:** breaking API or schema evolution where consumers cannot upgrade atomically. Expand to support both versions; migrate readers and writers; contract only after no old dependencies remain.[5][25]

**Runbook:** add additive optional structure; deploy readers that accept both representations; backfill; move write path; migrate consumers; verify no old field reads/writes; enforce new constraints; delete old structure.

**Test:** old app/new expanded schema, new app/expanded schema, mixed deployments and rollback with retained structures.

**Watch:** old-column reads/writes, backfill, replication mismatch, consumer migration completeness.

**Rollback:** before contraction, return application code while preserving expanded schema; after destructive contraction, require restore or forward repair.

**Pitfall:** expanding and contracting in a single release.

### 4.9 Backfill and change capture

**Use for:** stateful migration when service downtime or a one-time copy is unacceptable. Live migration often uses a consistent initial snapshot and log/change capture for subsequent updates.[16]

**Runbook:** inventory data and transformation rules; establish consistent snapshot identifier; backfill idempotently with checkpointing; apply post-snapshot changes in order within each aggregate; monitor lag and dead-letter records; reconcile; practise resuming from checkpoints; separately approve read and write cutovers.

**Test:** duplicates, missing/deleted records, out-of-order changes, schema evolution, backfill restart, large records, transaction boundaries, clock skew and reprocessing.

**Watch:** source-to-target lag, backlog growth, dead-letter count, per-aggregate divergence and oldest unprocessed mutation.

**Rollback:** old authority stays alive until verified; after transfer, reverse propagation or forward repair is mandatory.

**Pitfall:** treating a successful bulk copy as a consistent migration while ongoing writes continue.

### 4.10 Lift-and-shift

**Use for:** imminent hosting, supportability or physical location risk when deeper architectural change cannot responsibly happen before the deadline.

**Runbook:** map dependencies; reproduce runtime/network; baseline latency, failure and recovery; move representative workload; validate parity, backup and restoration; migrate the rest; stabilise; open a separately funded backlog for boundary modernisation.

**Watch:** performance, error rates, utilisation, recovery objectives and operating cost.

**Rollback:** move routing/environment back while data authority permits.

**Pitfall:** announcing architecture modernisation complete when coupling is unchanged.

### 4.11 Bounded big-bang replacement

**Use only if:** system is small, behaviour is well understood, consumers are controlled, downtime is acceptable, and maintaining concurrent implementations is riskier than one cutover.

**Runbook:** freeze scope; capture executable behaviour; rehearse complete data migrations; test capacity/security/recovery; run multiple cutover rehearsals; perform final delta; validate key journeys; open traffic; retain fallback window where feasible.

**Watch:** every critical business journey and reconciliation measure from first production transaction.

**Rollback:** rehearsed routing, restore/replay and business recovery—not an untested instruction to restore backup. Contingency planning guidance emphasises tested recovery procedures.[20]

**Pitfall:** undocumented legacy behaviour turns out to be the real production specification.

---
## 5. The ninety-day operating model

Ninety days is not enough to modernise a large estate. It **is** enough to validate a migration operating model, ship a meaningful boundary, establish reusable migration controls and produce evidence for whether scaling the approach is rational.

Two variants:

- **Variant A — foundations exist:** deployable environments, routing controls, instrumentation, continuous delivery and operational ownership are already available.
- **Variant B — foundations are weak:** the first quarter must establish a minimum migration platform while extracting a narrower boundary.

The following schedule assumes Variant A. It is an *illustrative plan*, not a benchmark or mandate.

```mermaid
flowchart LR
    A[Days 1-15 Discover] --> B[Days 16-30 Create seam]
    B --> C[Days 31-45 Build boundary]
    C --> D[Days 46-60 Backfill and shadow]
    D --> E[Days 61-75 Canary and authority gate]
    E --> F[Days 76-90 Stabilise and retire]
```

### 5.1 Ninety-day checklist

| Period | Deliverable | Exit criterion | Variant B adjustment |
|---|---|---|---|
| Days 1–10 | Outcome definition and baseline | Business KPI and reliability baseline agreed | Same |
| Days 1–15 | Business/runtime/data maps | Candidate boundaries ranked | Same |
| Days 10–20 | First boundary selected | Owner, data authority, rollback cost documented | Same |
| Days 15–30 | Interception seam | 100% legacy traffic safely passes through seam | Build minimum deployment/routing |
| Days 20–35 | Target contract and model | Consumer contract tests pass | Build contract testing |
| Days 25–45 | Implementation | Functional and operational acceptance pass | Narrow slice |
| Days 35–55 | Backfill and replication | Lag and reconciliation meet approved thresholds | Create reusable migration harness |
| Days 45–60 | Shadow execution | Differences classified and accepted | Add minimum telemetry |
| Days 55–65 | Internal exposure | No material service regression | Internal only |
| Days 60–75 | Canary progression | Business and reliability gates pass | Small tenant/region |
| Days 70–80 | New write authority | Recovery/repair procedure rehearsed | May defer |
| Days 75–85 | Production traffic migration | Residual old traffic negligible and explained | Partial production acceptable |
| Days 80–90 | Contract/retirement | One meaningful dependency removed | Formal retirement plan |
| Day 90 | Evidence review | Expand/change/stop decision recorded | Same |

### 5.2 Days 1–15: understand, do not build

Produce an **outcome hypothesis**: for example, reduce lead time for modifying a preference from six weeks to under one week without a higher change-failure rate.

Produce *migration SLOs*: allowable error budget, latency, correctness divergence, data-loss objective and recovery objective.

Rank three to five candidates. Map consumers, jobs, integrations, operators and regions. Identify data classification, residency, allowed transfers and other controls. Capture baseline incident, cost and delivery metrics.

Reject “new environment provisioned” as a business outcome.

### 5.3 Days 16–30: create reversible seams

Do not extract the new service before you can redirect an existing request or workflow. Create control over at least one of:

- request routing;
- a workflow step;
- an event subscription;
- an internal implementation binding;
- a data-access layer.

A seam that initially routes 100% to legacy is useful. It becomes the safe control point for the rest of the migration.

### 5.4 Days 31–60: build and prove equivalence

Backfill, shadow, replay representative inputs, test failure modes, reconcile state and inspect hidden dependencies. Discover behavioural and state problems *before* final cutover.

### 5.5 Days 61–75: expose progressively

Choose cohorts meaningful to the domain: internal accounts, a specific tenant, a lower-risk region, a transaction type or a traffic percentage.

Approve criteria before seeing outcomes. Canarying works best when the evaluation rules are set in advance instead of invented after a regression.[26]

### 5.6 Days 76–90: remove something

A quarter that only creates new systems has increased the estate, not demonstrably modernised it.

Remove at least one legacy writer, API, direct-table dependency, duplicate job, runtime or manual release procedure. Measure the permanent reduction.

> **Modernisation progress is measured partly by what disappears.**

---

## 6. Measuring what matters

Delivery-performance research has long used deployment frequency, lead time, change failure and recovery metrics, while evolving the details of their definitions over time. They are useful indicators, but they do not by themselves capture state-authority migration or elimination of coupling.[21]

### 6.1 Balanced scorecard

| Dimension | Metric | Why it matters |
|---|---|---|
| **Business** | Successful critical journeys | Technical success must preserve business outcome |
| | Capability change lead time | Measures reason for modernisation |
| | Migration-caused customer impact | Makes disruption visible |
| **Delivery** | Change lead time | Independent changeability |
| | Deployment frequency | Release flexibility |
| | Change failure rate | Delivery safety |
| | Failed-deployment recovery time | Reversibility |
| **Architecture** | Traffic on new boundary | Routing progress |
| | **Authoritative writes migrated** | Actual state cutover |
| | Shared mutable-data dependencies | Coupling removed |
| | Legacy inbound call volume | Decommission readiness |
| | Cross-team coordination per release | Organisational coupling |
| **Correctness** | Replication lag | Data cutover readiness |
| | Reconciliation mismatch by business impact | Integrity |
| | Shadow-output divergence | Behavioural parity |
| | Rollback drill time and success | Practical safety |
| | Age of transitional components | Prevents permanent bridges |

Avoid a single executive “70% modernised” number when all production writes still depend on the old system.

A more revealing dashboard separates dimensions:

**Traffic 84% | Writes 38% | Data 61% | Consumers 47% | Legacy runtime retired 12%**

These are *illustrative values*. Their inconsistency is the point: a weighted overall completion claim conceals different forms of dependency.

### 6.2 Boundary SLOs

Every migrated capability needs an availability target, latency target where relevant, correctness/invariant target, freshness target for replicated data and migration mismatch threshold.

Treat the measurements as release controls, not passive dashboard decoration.

### 6.3 Team design

Systems and team structures influence one another; trying to create independently deployable boundaries while leaving ownership fragmented creates a basic mismatch.[14][15]

**Domain team:** accountable for behaviour, state contract, release, reliability, support and business outcomes.

**Platform team:** self-service deployment, routing, identity/policy controls, observability and migration/reconciliation primitives. Research on software-team organisation identifies platform teams as one of the recurring models supporting continuous delivery.[15]

**Reliability expertise:** equips teams to own production and assists consequential cutovers; should not become the sole production owner.

**Architecture/governance:** defines guardrails, cross-domain contracts and exception review, with concentrated scrutiny of irreversible decisions.

**Security/compliance:** defines machine-testable controls and approval evidence early, particularly for regional movement.

Platform engineering is most useful when it reduces domain-team cognitive load without replacing autonomy with a central ticket queue.[22]

### 6.4 Funding model

Fund three distinct buckets:

**Domain outcome:** a capability migration tied to business/delivery improvement.

**Platform enablement:** reusable routing, observability, policy, data-copy and verification facilities.

**Legacy retirement:** explicit budget for deleting old code, migrating consumers, archiving data, obtaining audit evidence and shutting down services.

The third bucket is easy to omit. Without it, creating the replacement system can be financially rewarded while removing the old one has no owner.

A boundary is not financially complete until avoidable legacy run costs and retirement ownership are explicit.

### 6.5 Governance gates

| Gate | Required evidence |
|---|---|
| Boundary accepted | Business scope, invariants, authority, consumers, owner |
| Shadow allowed | Security review, capacity, side effects suppressed |
| Canary allowed | SLOs, rollback test, dashboards, support and incident readiness |
| Write-authority transfer | Reconciliation, fencing/idempotency, recovery plan, approvals |
| Old writer disabled | Stable new path through approved business cycle |
| Destructive contraction | No old consumers, archival/restore and retention addressed |
| Decommission | Audit/retention obligations satisfied, recovery artefacts archived |

Architecture review should focus on **write-authority transfer** and **destructive contraction** because those decisions tend to be more irreversible than deploying a new compute process.

### 6.6 Standard migration capabilities

A useful paved road offers health/telemetry, routing/canary controls, contract tests, compatibility checks, data-copy/checkpoint tooling, reconciliation, identity/policy, rollback automation, inventory and placement rules. Each should be a product with clear users, not a prerequisite mega-platform blocking every domain team.

---

## 7. Worked examples: decisions and failure points

### 7.1 High-volume identity-adjacent profile

Applied migration case-study literature also documents incremental strangler extraction and its performance considerations.[24]

**Situation.** A central legacy application owns authentication-adjacent profile data in a shared active-passive database. Many consumers access it directly. A replacement distributed data foundation exists, but several regions have different locality constraints.

**Bad plan:** copy every table, change connection strings, then refactor each consumer. This changes storage without establishing business ownership.

**Boundary-first decision:** extract *profile preferences* rather than the whole identity record. Preferences are usually less entangled with the invariants of core authentication, have an independent change cadence and can tolerate explicitly defined propagation to downstream consumers.

**Pattern stack:** strangler (migration), facade (interception), anti-corruption layer (semantic protection), expand–contract (contract evolution), change capture (data), parallel read comparison (proof), canary (rollout), regional placement policy (last mile).

**Sequence:**

1. Establish a stable profile contract. Initially route every call to the legacy implementation.
2. Inventory direct readers and writers; no new direct accesses permitted.
3. Backfill target preference state while legacy remains authoritative.
4. Catch up mutations; compare invariant and record projections.
5. Serve shadow reads and explain mismatches.
6. Canary new reads for selected accounts/regions.
7. Prepare and test a write-authority handover with fencing of old writers.
8. Move new authoritative writes, retaining a bounded compatibility interval and repair path.
9. Observe at least one meaningful business cycle.
10. Remove old preference writes, then direct-table readers and obsolete schema.

**Failure point A — a batch job writes preferences directly.** Stop expansion. Migrate or intercept the job first. Otherwise old-system bypasses will corrupt authority after cutover.

**Failure point B — a regional placement rule forbids target storage.** Keep that region behind the common contract with a local implementation; do not block all regions.

**Why strangler:** independently migratable domain, many asynchronous consumers, ongoing business change and low tolerance for an estate-wide cutover.

**North-star metric:** share of *authoritative preference writes* on the new boundary, not only read traffic.

### 7.2 High-consequence financial decision engine

**Situation.** A monolith calculates financial eligibility. Re-implementation is desirable, but a wrong result can create material harm or financial exposure.

**Decision:** progressive strangler with shadow/parallel execution. Initially the new engine receives identical inputs but its answers are never used to commit a business decision.

**Execution:** capture a representative corpus, including rare exceptions; normalise timestamps and nondeterministic fields; compare by policy, segment, amount and consequence; classify every material discrepancy; approve intentionally changed semantics separately; then serve a limited cohort.

**Go/no-go:** no unexplained high-consequence mismatch; accepted semantic changes are documented; latency and availability SLOs pass; rollback to old decision path is tested.

**Failure point — headline agreement is 99.9%.** Do not conclude success until the remaining 0.1% has been segmented by risk. A single missing severe-case rule can outweigh thousands of harmless matches.

**Why not big bang:** behavioural uncertainty is more consequential than implementation difficulty.

### 7.3 Infrastructure deadline before architectural readiness

**Situation.** An ageing runtime must leave its environment within six months for external support reasons. Shared data and minimal tests make a combined refactor and move unattractive.

**Decision:** rehost first, strangle later.

**Execution:** reproduce the current topology in a supported environment, prove connectivity, observe performance and recoverability, rehearse cutover and rollback, migrate, stabilise, and only then begin capability extraction.

**Failure point — the move is declared “modernisation complete”.** Prevent this by making risk-retirement and architecture-decoupling separate funded outcomes.

**Executive message:** the first stage reduces an immediate operating risk; it does not automatically improve coupling.

### 7.4 Last-mile sovereignty-constrained region

**Situation.** Most regions can use the new domain platform, but one region cannot yet meet its data/control-plane/operational constraints with the target design.

**Wrong choice:** hold the worldwide migration until the final region can use the same physical implementation.

**Boundary-first decision:** adopt a common logical contract with a bounded regional legacy implementation. Sensitive state remains under the appropriate authority; approved derived attributes cross boundaries only where policy allows; degraded mode is locally specified. Relevant personal-data transfer obligations must be assessed, not assumed.[18][19]

**Failure point — the region requires independent operation but identity/token validation depends on a global control plane.** Create a regional operational design and appropriate local trust/control capabilities, or limit functionality until the requirement can be met.

**Why this works:** placement differences are confined to the boundary implementation, rather than permanently forking business logic.

### 7.5 Stateful active-passive to distributed active-active foundation

**Situation.** A central state store has a single write authority with a passive recovery environment. The desired target can accept transactions in more than one region. That change is **not merely a replication upgrade**: it changes the failure, consistency and conflict model.

**First decision:** define what *active-active* actually means for each aggregate. Some operations may support local independent writes; others require home-region ownership, coordination, or strict serialisation. Do not promise globally concurrent writes without a defined conflict invariant.

**Recommended classification:**

| Aggregate class | Default authority model | Why |
|---|---|---|
| Commutative counters/telemetry | Partitioned/local writes with merge rules | Some operations can converge safely |
| Preferences with explicit last-write policy | Regional authority or specified conflict resolution | Acceptable only if lost-update semantics are understood |
| Unique identifiers / usernames | Uniqueness coordinator or authority partition | Prevent duplicate acceptance |
| Balance / spend limit / entitlement | Single logical authority per invariant or coordinated protocol | Avoid conflicting irreversible approvals |
| Immutable append-only events | Unique event IDs and ordered projections | Replay and deduplication are explicit |

**Execution sequence:**

1. Inventory state and consistency invariants. Assign each aggregate class a write-authority model.
2. Measure current peak traffic, write rates, RPO/RTO, staleness tolerance and cross-region latency budget.
3. Introduce stable service/data-access contracts; initially leave authority in the current writer.
4. Create target schemas, migration transforms, initial snapshot and resumable backfill.
5. Capture source mutations, including deletes, with per-aggregate ordering and deduplication.
6. Reconcile target state and domain invariants continuously.
7. Route shadow reads, then canary read traffic to target.
8. Define **fencing**: an old writer cannot commit after authority transfer. Explicitly handle in-flight writes and retries.
9. Move *one aggregate class or ownership partition at a time*; record a cutover epoch/version.
10. Verify write acceptance, replay, conflict handling and region isolation under failures.
11. Retain recoverable backward compatibility until rollback/repair has been rehearsed and the hold period completes.
12. Remove old state authority; later remove remaining interfaces and infrastructure.

**Failure point A — target accepts writes in two regions but has no conflict policy.** Stop. Determine what happens when two valid concurrent requests violate the same invariant. Availability is not a substitute for correctness.

**Failure point B — replication looks caught up but one stream contains dead-lettered mutations.** Stop. Aggregate lag is insufficient; require per-partition completeness and zero unresolved critical records.

**Failure point C — “rollback” is a traffic switch after target-only writes.** Not acceptable without an approved reverse-replication, replay or forward-repair mechanism.

**Useful evidence:** mutation replay checks, business aggregate equality, aggregate-specific reconciliation, oldest outstanding event, fencing logs, recovery drills and read-your-writes test results.

This example is an operational synthesis of migration, dual-write and distributed consistency principles rather than a claim that a single storage engine or algorithm fits all systems.[16][17][23]

---

## 8. Practical go/no-go gates

The following thresholds are **examples**, not universal standards. Derive limits from business impact, established SLOs, critical transaction classes and recovery obligations.

| Gate | Illustrative evidence | No-go condition |
|---|---|---|
| **Seam inserted** | 100% old traffic through seam with no material change | Bypasses or unexplained error/latency regression |
| **Backfill complete** | All intended records and deletes processed; checkpoints reproducible | Missing partitions or silent dropped rows |
| **Catch-up complete** | Lag under agreed bound across all critical partitions | Growing backlog, unknown gaps or stuck stream |
| **Semantic shadow** | Consequential classes have zero unexplained mismatch | Critical unexplained discrepancy regardless of aggregate match % |
| **Canary ready** | SLOs, business outcome and rollback tests green | Unknown cohort blast radius |
| **Write transfer** | Old writer fenced; replay/idempotency and restore strategy demonstrated | Split-brain write authority or no state recovery plan |
| **Stable at 100%** | Observed through peak and business cycle | Delayed defects or unresolved accounting/invariant mismatch |
| **Contraction** | No old consumers or contractual obligation unaddressed | Direct-table writers/readers still active |
| **Retirement** | Retention, audit, recovery evidence and financial closure | Runtime/data needed for mandatory historical operation |

### 8.1 A sample routing contract

The following pseudocode illustrates separating read routing from write authority:

```text
route(request):
    boundary = identify_business_capability(request)
    cohort = classify_request_cohort(request)

    if request.is_read:
        if new_read_enabled(boundary, cohort):
            return target.read(request)
        return legacy.read(request)

    authority = authority_registry.lookup(boundary, request.aggregate_id)
    if authority == LEGACY:
        return legacy.write(request, idempotency_key=request.key)
    if authority == TARGET:
        return target.write(request, idempotency_key=request.key)

    fail_closed("No valid write authority")
```

**Required invariants:** exactly one logical authority per aggregate; changes to authority are versioned/fenced; retries are idempotent; routing decisions are observable; all bypasses are detected.

### 8.2 A sample reconciliation contract

```text
for each aggregate_id in migration_scope:
    old = normalise(legacy.snapshot(aggregate_id, consistent_at=T))
    new = normalise(target.snapshot(aggregate_id, consistent_at=T))

    compare_structural_state(old, new)
    compare_business_invariants(old, new)
    classify_differences_by_business_consequence()

block_write_cutover_if(any_unexplained_critical_difference)
```

A valid comparison needs a consistent logical checkpoint or a well-defined freshness envelope. Comparing two systems at unrelated instants can manufacture false mismatches.

### 8.3 Operational rollback: the uncomfortable but necessary truth

Rollback must be defined at two levels:

**Before write-authority transfer:** revert routing/implementation, while the source remains authoritative. This is often straightforward.

**After write-authority transfer:** merely reverting application code can violate data integrity. A safe strategy must specify a reverse feed, durable replay, compensating transactions, deliberate forward repair or an explicit no-rollback policy with recovery objectives.

For irreversible business events, “roll forward safely” may be the only correct recovery. Deciding this on incident day is too late.

---

## 9. Common failure modes

| Failure mode | Why it happens | Mitigation |
|---|---|---|
| “Strangler” means new services exist | Traffic and state ownership ignored | Track reads, writes, consumers and deletion separately |
| First boundary is hardest domain | Leadership chooses high-visibility flagship | Choose representative but survivable slice |
| Shared database stays forever | Extraction stops at service facade | Plan authority movement from day one |
| New model copies legacy schema | Speed prioritised over semantics | Define domain model, translate through ACL |
| Dual writes normalised | Two calls look simple | Use explicit authority and recoverable propagation |
| Canary monitors only CPU/errors | Easy infra metrics dominate | Add business decision and correctness metrics |
| Flag never removed | No lifecycle owner | Removal criterion and expiry review |
| 100% traffic claimed complete | Routing is easily visible | Require state/dependency retirement |
| Old consumers unknown | Direct storage access | Runtime and database telemetry |
| Platform becomes approval committee | Central standards overreach | Self-service guardrails |
| Services created used as KPI | Easy to count | Measure coupling deleted |
| Backfill accepted by row count | Cheap validation | Check business invariants and deletes |
| Contract immediately after cutover | Desire to tidy | Hold through real business cycle |
| One region blocks all | Physical architecture assumed identical | Logical contract, regional implementation |
| Rewrite takes years | End-state perfection pursued | Deliver real production slices continuously |
| Decommission never funded | Focus on building new | Ring-fence legacy-retirement funding |

---

## 10. The ten rules to remember

1. **Strangle capabilities, not whole applications.**
2. **Find the transaction and data boundary before drawing the service boundary.**
3. **One authoritative writer per business aggregate.**
4. **Copying data is normal; ambiguous ownership is not.**
5. **Traffic cutover and write-authority cutover are different decisions.**
6. **Use anti-corruption layers when semantics differ, not merely when protocols differ.**
7. **Parallel-run logic when correctness matters more than migration speed.**
8. **Flags and canaries control exposure, not persistent-state rollback.**
9. **Contract only after the compatibility interval has proved unnecessary.**
10. **Every migration iteration should ultimately delete something.**

The research and engineering literature supports the broad direction: incremental replacement, coherent domain boundaries, deliberately safe coexistence and progressive deployment lower risk relative to a single irreversible transition. The particular choice and sequencing are still engineering decisions, not universal recipes.[2][5][9][26]

---

## References

The numbers below correspond directly to literal inline references in the text. Each entry uses exactly the format `[number] URL`, and each URL points to the original publication or an authoritative host. Sources may name companies or technology providers; the main playbook remains implementation-agnostic.

[1] https://www.martinfowler.com/bliki/OriginalStranglerFigApplication.html

[2] https://martinfowler.com/bliki/StranglerFigApplication.html

[3] https://samnewman.io/patterns/refactoring/strangler-fig-application/

[4] https://martinfowler.com/bliki/BranchByAbstraction.html

[5] https://martinfowler.com/bliki/ParallelChange.html

[6] https://www.martinfowler.com/articles/feature-toggles.html

[7] https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-204.pdf

[8] https://martinfowler.com/articles/microservices.html

[9] https://doi.org/10.3390/software1040018

[10] https://researchoutput.ncku.edu.tw/en/publications/microservice-migration-using-strangler-fig-pattern-and-domain-dri/

[11] https://doi.org/10.1016/j.jss.2025.112537

[12] https://conf.researchr.org/details/ecsa-2026/ecsa-2026-technical-track/32/Multi-View-Evaluation-of-Microservice-Decompositions-via-Bounded-Context-and-Data-Own

[13] https://onlinelibrary.wiley.com/doi/10.1002/spe.70062

[14] https://www.melconway.com/Home/Committees_Paper.html

[15] https://arxiv.org/abs/2008.08652

[16] https://www.inderscience.com/info/e_inarticle.php?artid=73942

[17] https://developers.redhat.com/articles/2021/09/21/distributed-transaction-patterns-microservices-compared

[18] https://eur-lex.europa.eu/eli/reg/2016/679/oj/eng/

[19] https://www.edpb.europa.eu/documents/recommendation/recommendations-012020-on-measures-that-supplement-transfer-tools-to_en

[20] https://csrc.nist.gov/pubs/sp/800/34/r1/upd1/final

[21] https://dora.dev/insights/dora-metrics-history/

[22] https://www.frontiersin.org/journals/computer-science/articles/10.3389/fcomp.2026.1814498/full

[23] https://martinfowler.com/articles/patterns-of-distributed-systems/

[24] https://doi.org/10.1109/ICS51289.2020.00107

[25] https://www.tim-wellhausen.de/papers/ExpandAndContract/ExpandAndContract.html

[26] https://sre.google/workbook/canarying-releases/

[27] https://hillside.net/plop/plop2002/final/DomainDrivenDesign_Excerpt_PLoP2002.pdf
