LEGACY MIGRATION SIMULATOR
Strangler Fig
Move a fictional monolith to a new system one workflow at a time, behind a routing facade. No big-bang weekend: every step has a price and a risk.
- Build the routing facade.
- Each sprint, spend the team’s capacity: build, dual-run and route modules.
- Retire the legacy code, and watch tickets, drift and upkeep.
- Sprint
- 0 / 12
- On the new system
- 0%
- Support tickets
- 00 this sprint
- Data out of sync
- 0records
- Capacity next sprint
- 10 / 12 pts
- First users moved
- Not yet
The estate
Sprint 0- Star size: daily usage
- Colour: risk (teal low, amber medium, coral high)
- Violet ring: uses legacy session code (dashed until the session bridge is in place, then solid)
- Line: shared tables (amber dashes: drifting)
- Teal dashes: kept in sync by a sync bridge
- Faint outline: legacy code still there, the rollback path
- Coral pulse: tickets in the sprint shown
Sprint log
Sprint 0Run a sprint to see what happened.
Directory & notices
Staff directory
On the monolithLook up a colleague’s desk, phone and team.
- Daily usage
- 10 / 10
- Build effort
- 2 pts
- Risk
- Low risk
- Data
- Reads only
- Session
- No shared session code
- Shares tables with
- Announcements
Users are served by the monolith.
Steps for this module
Build the new version
2 ptsGain Ready to dual-run or route next sprint. No user sees it yet.
Risk Delivers nothing until traffic moves to it.
Sprint 1 plan
0 of 10 points planned- Monolith upkeep
- 2
- Dual-run triage
- 0
- Double maintenance
- 0
- Hotfixes
- 0
Nothing planned yet. Pick a module, or let the suggestion fill the sprint.
Suggestions use only what you can see, never the hidden defects.
Transitional architecture
Routing facade
3 ptsGain Every request passes through one router you control. No module can move without it.
Risk Transitional architecture: built to be removed at the end, and it must not become a single point of failure or a bottleneck. This model charges only for building it.
Session bridge
2 ptsGain Modules that still rely on the monolith’s session code can be dual-run and routed.
Risk One more temporary piece to keep working and later remove. This model charges only for building it.
Sync bridges, one per group of shared tables
Gain Two-way sync: an initial load plus change data capture in both directions keeps the old shared tables and the new stores in step. Reconciles what is already out of sync, stops new drift and lets dual-runs compare writes.
Risk In reality it needs looking after until the whole cluster has moved, and change data capture lags. This model charges only for building it and treats it as instant.
- Facilities
- Assets & access
- Finance
- People
Same estate as a big-bang rewrite
- Your migration
- Big-bang rewrite
| Your migration | Big-bang rewrite | |
|---|---|---|
| First users moved | — | Sprint 4 |
| Tickets so far | 0 | 255 |
| Worst sprint | 0 | 180 |
| Legacy switched off | — | Sprint 8 |
| Average share on the new system | — | — |
The rewrite gets the same team, build effort, upkeep and hidden defects, and it pays for one bulk copy of each group of shared tables. It builds no facade or bridges and runs no dual-runs. It is also the best case: its scope is fully known up front and nothing changes while it is built. So in this model it can finish sooner, and over the full twelve sprints it can even carry more traffic on average. What it gives up: no user benefits before sprint 4, every hidden defect reaches users in the same sprint, and the only rollback is the whole system.
Sprint by sprint
| Sprint | Your migration: On the new system | Your migration: Support tickets | Big-bang rewrite: On the new system | Big-bang rewrite: Support tickets |
|---|---|---|---|---|
| 1 | — | — | 0% | 0 |
| 2 | — | — | 0% | 0 |
| 3 | — | — | 0% | 0 |
| 4 | — | — | 100% | 180 |
| 5 | — | — | 100% | 75 |
| 6 | — | — | 100% | 0 |
| 7 | — | — | 100% | 0 |
| 8 | — | — | 100% | 0 |
| 9 | — | — | 100% | 0 |
| 10 | — | — | 100% | 0 |
| 11 | — | — | 100% | 0 |
| 12 | — | — | 100% | 0 |
Wave plan
The order you moved modules in, why, how each was verified and how to back out. Built from your run.
Model, not reality
Everything here is authored for teaching. The monolith, its twelve workflows, the usage figures, the hidden defects, the tickets and the record counts are invented; none of it comes from a real system or employer. Routing is all-or-nothing per module, where a real facade can move a percentage of traffic. The facade and bridges cost only their build here; real transitional architecture also has to be looked after and, at the end, removed. The sync bridge is two-way and instant, where real change data capture lags. There are no schema changes, and people, budgets and politics are left out. Costs are points for a made-up team of fixed size. Use it to reason about order and trade-offs, not to estimate a project.
Go deeper in the LabSCHEMA SHIFTPlan a zero-downtime migration with expand/contract steps, backfill and compatibility gates. (opens in a new tab)Where the rules come from
- Martin Fowler, “Strangler Fig Application” (updated 2024) (opens in a new tab)
The name and the idea: grow the new system around the old one in small pieces. Transitional architecture can look like waste, but the lower risk and earlier value outweigh its cost.
- Microsoft Azure Architecture Center, “Strangler Fig pattern” (opens in a new tab)
The facade that routes each request to old or new, and must not become a single point of failure or a bottleneck. Data stores that both systems use at the same time, hence drift when a group of shared tables is split without sync. Rollback stays possible until the legacy objects are removed; after that you restore them and replay data changes. An initial load plus change data capture from the old database to the new one.
- Cartwright, Horn and Lewis, “Transitional Architecture” (2022) (opens in a new tab)
Facade, bridges and sync are temporary software you build knowing it will be thrown away.
- Cartwright, Horn and Lewis, “Feature Parity” (2021) (opens in a new tab)
Why the big-bang comparison is a best case: people “greatly underestimate” the effort of matching everything the old system does, and documenting it keeps uncovering more to rebuild. The rewrite here meets no such surprises.
- GitHub, Scientist (library README) (opens in a new tab)
Dual-run: the old path’s result is always returned while the new one is compared, and wrapping code that changes data is not safe. For writes the README suggests writing to both systems and checking at read time. This model simplifies that: without a sync bridge only reads are compared, with one writes are too.
- Zalando Engineering, “Parallel Run Pattern” (2021) (opens in a new tab)
A parallel run adds load and effort, needs care with non-idempotent writes, and moves endpoints one at a time once they are consistent.
- Pete Hodgson, “Feature Toggles” (2017) (opens in a new tab)
A route you can flip back quickly works as a kill switch; every toggle left in place has a carrying cost.
- Microsoft Azure Architecture Center, “Implement the Transactional Outbox Pattern by Using Azure Cosmos DB” (opens in a new tab)
Saving a change and then telling another system without one shared transaction can lose events, and lost events can leave data inconsistent. The drift in this model is the blunter case: the other store is not told at all.