Legacy Modernisation: Strangler Fig in Practice
How to modernise a legacy system without a big-bang rewrite. Strangler Fig pattern, route-by-route migration, and the ladder from old to new across 6-12 months.
Table of contents
- When does modernisation actually pay back?
- What is the cost of letting legacy stay?
- What does the Strangler Fig migration look like?
- What is the typical 12-month migration timeline?
- What does the migration tracking artifact look like?
- How does this scale to multi-team?
- What failure modes does modernisation introduce?
- When is modernisation the wrong answer?
- Where should you go from here?
The system that has run production for ten years has earned the right to retirement, not the right to a 6-month rewrite that fails. This case study shows the Strangler Fig migration that ships value each quarter, the artifacts that make the migration honest, and the traps that derail modernisation projects.
When does modernisation actually pay back?
Three signals.
Maintenance cost is rising. Bug fixes take longer; new hires take longer to ramp; tooling around the legacy is ageing out (old framework, old language version, vendor deprecating).
New features blocked. "We can't add this without refactoring foundation X" said for the third time. The legacy is no longer just slow to maintain - it actively prevents business outcomes.
Hiring difficulty. Engineers do not want to work on COBOL/old-PHP/legacy-stack. Attrition rises; replacement is hard. The cost of legacy includes the cost of not being able to staff it.
If maintenance is fine, hiring is fine, and new features ship, modernisation might be a vanity project. Run the numbers.
What is the cost of letting legacy stay?
Three slow-burn failure modes.
Compounding cost. Each year the legacy is harder than the last to change. By year 5 of "we'll modernise next year", the cost has doubled.
Talent flight. The engineers who could have led modernisation leave because no one is doing it. Now the legacy has fewer experts and is harder to migrate.
Strategic vulnerability. Competitors with modern stacks ship features faster. The legacy that was once a competitive advantage is now the moat preventing competition.
What does the Strangler Fig migration look like?
flowchart TB
Client[Client] --> Proxy[Routing layer]
Proxy -->|Route A| New[New system<br/>built alongside]
Proxy -->|Route B and others| Old[Legacy system<br/>still serves]
New --> NewDB[(New database)]
Old --> OldDB[(Legacy database)]
NewDB -.sync from.- OldDB
A routing layer (reverse proxy, feature flag, API gateway) sends some routes to new code and others to legacy. Each quarter, more routes move. Eventually legacy serves nothing and is retired.
What is the typical 12-month migration timeline?
gantt
title Strangler Fig 12-Month Plan
dateFormat YYYY-MM-DD
section Q1 Foundations
Routing layer + observability :a1, 2026-07-01, 30d
First route migrated :a2, after a1, 30d
section Q2 Read paths
Read-heavy routes (lower risk) :b1, 2026-10-01, 60d
Read replica from legacy DB :b2, 2026-10-01, 30d
section Q3 Write paths
Write paths with dual-write :c1, 2027-01-01, 60d
Validate consistency :c2, after c1, 30d
section Q4 Retirement
Final routes migrated :d1, 2027-04-01, 60d
Legacy decommissioning :d2, after d1, 30d
Post-mortem + handover :d3, after d2, 30d
Quarter 1 builds the migration infrastructure (routing, observability, parallel data store). Quarter 2 migrates read-heavy routes (low risk). Quarter 3 migrates write paths with dual-write for safety. Quarter 4 retires legacy.
What does the migration tracking artifact look like?
# Modernisation Tracker — {{ System Name }}
## Goal
Replace legacy {{ X }} with new {{ Y }} by 2027-06-30.
## Migration progress
| Route | Traffic Old | Traffic New | Status | Notes |
|-------|-------------|-------------|--------|-------|
| GET /products | 0% | 100% | Migrated | Stable since Q2 |
| GET /products/:id | 0% | 100% | Migrated | Stable since Q2 |
| POST /orders | 90% | 10% | In progress | 10% canary; expand Q3 |
| GET /reports | 100% | 0% | Not started | Q4 target |
| ... | | | | |
## KPIs
- Traffic on new: 35% (target Q3 end: 60%)
- Incident rate on legacy: 0.3/month (was 0.4)
- New-feature time-to-ship: 2 wks (was 4 wks for legacy team)
## Active risks (RAID)
- R1: Dual-write consistency edge case discovered in Q2
- R2: One legacy report has no documented schema
## Decommissioning checklist
- [ ] All routes at 0% legacy traffic
- [ ] Legacy DB last-modified > 30 days
- [ ] Legacy code archived to read-only repo
- [ ] On-call rotation removes legacy
- [ ] Servers turned off
- [ ] Cost savings reported to sponsor
The tracker becomes the status report attachment for sponsor reviews. Visible quarterly progress is the only way modernisation survives leadership changes.
How does this scale to multi-team?
flowchart TB
Mod[Modernisation team<br/>owns routing + new system] --> Team1[Product Team A<br/>uses new system]
Mod --> Team2[Product Team B<br/>migrates own routes]
Mod --> Team3[Product Team C<br/>contributes domain]
Mod --> Sponsor[Quarterly sponsor review]
A dedicated modernisation team owns the migration; product teams contribute their domain expertise. The modernisation team's RACI shows Accountable for migration, Consulted by product teams.
What failure modes does modernisation introduce?
- Forever migration. Project enters year 3 with 60% on new. Mitigation: explicit decommission deadline; if not on track, cut scope (which routes will not migrate) and retire those parts of legacy on schedule.
- Two systems forever. Legacy keeps running because some customer relies on it; new system never feels complete. Mitigation: customer comms early; deprecation announced before migration completes; willingness to lose some legacy customers.
- Performance regression. New system is slower than legacy for some routes. Mitigation: per-route latency budgets in observability; rollback capability per route.
- Knowledge loss. Engineer who knew legacy intricately leaves before migration completes. Mitigation: pair them with migration team; record their tribal knowledge as ADRs (chapter 19).
When is modernisation the wrong answer?
Two cases.
Legacy actually fine. A boring system that works well, has low maintenance cost, and supports business priorities does not need modernisation. Reformatting a CSS file once a year is not enough reason.
No team available. If you cannot dedicate a team, do not start modernisation. Half-team modernisation drags forever and delivers nothing.
The migration earns its 12-18 months when the legacy actively costs the business money. Below that, leave it alone.
Where should you go from here?
Last case study: vendor managed project - the case where most of the work is outside your team. After that, the meta closing chapters (checklist, conclusion) wrap the series.