DevOps Peach

System Design for DevOps · Reliability, Deployments and Migrations · Lesson 5 of 5

Branch by Abstraction and the Strangler Fig

Branch by abstraction replaces a component inside a codebase behind an interface while everyone keeps committing to main; the strangler fig replaces a whole system route by route behind a proxy until the old one can be switched off.

Practice interactively →

Big-bang rewrites are risky: months without value, then one scary switch. Two techniques make large changes incremental.

flowchart LR
  subgraph BBA["Branch by abstraction (inside the code)"]
    C["Callers"] --> I["Interface: PaymentGateway"]
    I --> OLD["LegacyPayments"]
    I -.->|"flag"| NEW["StripePayments"]
  end
  subgraph SF["Strangler fig (around the system)"]
    U["Users"] --> PX["Proxy / gateway"]
    PX -->|"/cart"| NS["New cart service"]
    PX -->|"everything else"| MONO["Legacy monolith"]
  end
  %% step C: All callers are changed to use an abstraction instead of the old component directly.
  %% step I: The interface hides which implementation runs.
  %% step NEW: The new implementation is built behind the interface and switched on with a flag, gradually.
  %% step PX: For whole systems, a proxy sits in front of the legacy system.
  %% step NS: Routes move one by one to new services until the legacy system has nothing left.

Branch by abstraction (steps)

  1. Create an abstraction (interface) over the component you want to replace.
  2. Change all callers to use the abstraction — still backed by the old implementation.
  3. Build the new implementation behind the same interface, committing to main (no long-lived branch).
  4. Switch callers gradually with a feature flag; compare results if you can.
  5. Remove the old implementation and, optionally, the abstraction.

It is "branching" in the code instead of in Git — trunk-based development stays possible during a big change.

Strangler fig (steps)

  1. Put a proxy or API gateway in front of the legacy system (no behaviour change).
  2. Pick one route or capability with clear boundaries (e.g. /cart).
  3. Build it as a new service; route that path to it — maybe 5% first.
  4. Repeat route by route; the legacy system shrinks.
  5. Switch off the legacy system when no traffic reaches it.

Named after a fig that grows around a host tree until it replaces it.

Data during a strangler migration

The hardest part. Options: the new service owns new data and calls the monolith for the rest; sync with change data capture; or an anti-corruption layer that translates between the old model and the new one.

When to use which

Situation Technique
Replace a library, ORM, payment provider inside one codebase Branch by abstraction
Break a monolith into services, move to a new platform Strangler fig
Both at once Common: strangle the system, abstract inside each piece

Traps: a strangler proxy that becomes a permanent second system; extracting the most tangled module first; long-lived feature branches instead of abstraction; never deleting the old path.

Practice interactively →