Strategy & Transformation
How to Calculate ROI for AI and Software Modernization
A practical, finance-ready framework for comparing AI and modernization investment with the current-state cost, realistic benefits, delivery risk and time to value.
operationalwrocław--:-- cet
∕ insights / strangler-fig-pattern.md
Strangler Fig Pattern
Learn how the strangler fig pattern replaces legacy systems piece by piece, when to use it, and how to finish the migration.
>_article.meta

Your roadmap keeps slipping, customers still depend on the system that's slowing you down, and a full rewrite would freeze the features that pay for it. That's exactly where the Strangler Fig pattern earns its keep. Don't bet the company on one cutover. Replace the system slice by slice, prove each slice in production, and retire the old code on a date you choose.
Say your SaaS company runs a six-year-old monolith. Quarterly releases keep slipping, and the board asks why a feature that should take weeks takes months. The instinct in the room is predictable. Rip it out and rebuild it properly.
That instinct usually creates a second problem. Your team now maintains two codebases at once, one that earns revenue and one that might earn revenue later. Product accepts a feature freeze so the new team can catch up. The freeze stretches. Competitors ship while you're rebuilding plumbing nobody can see.
A rewrite doesn't fail because engineers can't write the new system. It fails because the business can't wait quietly while they do.
The Strangler Fig pattern takes the opposite bet. It replaces functionality slice by slice while the old system keeps serving customers. Value arrives earlier, each step can be rolled back, and spending spreads across smaller decisions you can revisit with real evidence.
Be honest about the trade-off. Calendar time to full replacement can be longer, and you'll pay for routing, synchronization, and governance along the way. If nobody owns finishing the job, you'll end up running two systems and paying for both.
You'll leave with a plain definition, a working procedure, the architecture pieces that matter, a fit test, and a finish-line checklist. Use them to decide, then commit.
A strangler fig starts life in the upper branches of a host tree. It sends roots down to the ground, grows strong enough to stand alone, and eventually becomes self-sustaining. The host may die, but the fig keeps its shape.
The image below shows why the metaphor stuck. The new growth doesn't replace the old structure in one event. It surrounds it, supports itself, and takes over gradually.

Map that to software and the definition is simple. The host is your legacy system, the fig is the new system, and the roots are the routing layer that takes over one capability at a time. You build new components around the edges of the old system, route selected capabilities to them, and shrink the legacy scope until you can switch it off.
Martin Fowler connected the natural process to software after observing strangler figs during a vacation in Queensland, Australia, in 2001, and Fowler's original Strangler Fig Application post first published the "Strangler Application" idea on 29 June 2004 as an alternative to a high-risk, all-at-once rewrite, replacing functionality incrementally over several years. The term was later refined to "Strangler Fig Application." The foundational principle is coexistence, with old and new systems operating together while capabilities move.
If you want the wider context for where this pattern sits among other design choices, AppJet's guide to architectural patterns is a useful companion before you commit to a target architecture.
Don't confuse the pattern with its most common implementation. It does not require microservices. The replacement can be monolith modules, APIs, modular applications, or services behind a routing layer. What matters is controlled, staged displacement, not the size of the deployment unit.
That reframes the decision. You're not choosing between rewrite and retain. You're choosing a sequence of smaller replacements, each with its own evidence, rollback, and retirement date.
Start with evidence, not preference. In Fowler's 2024 account of applying the approach to mobile applications, a proof of concept using modular micro-apps significantly shortened the path to first value compared with the estimated duration of a complete rewrite, while the median development cycle time improved by 50% relative to the existing legacy mobile application. That's not a promise for your system. It's proof that incremental replacement can improve delivery speed before decommissioning is complete.
Use that distinction when you judge fit. The pattern earns its overhead when a failed cutover is expensive, the old system must keep running, and you can identify seams worth extracting. It wastes money when the system is small enough to change directly.
| Situation | Fit | Why | Better option when weak |
|---|---|---|---|
| Large monolith that must keep shipping | Strong fit | Value arrives slice by slice with rollback at each step | Not applicable |
| Legacy mobile app with long release cycles | Strong fit | Modular micro-apps shorten time to first value | Not applicable |
| Small application with few modules | Weak fit | Routing layer overhead outweighs the benefit | Refactor in place |
| Clean replacement, few integrations, short deadline | Weak fit | A bounded rewrite can be cheaper and faster | Scoped rewrite with a cutover rehearsal |
| Regulated system with a hard cutover date | Mixed | Parallel running needs strong proof of parity | Parallel run with a rehearsed cutover |
| Broken data model with no clear owners | Caution | Dual writes create divergent state | Fix data ownership first, then slice |
Read the caution row seriously. If nobody can say who owns customer, order, or billing data, slicing code will just distribute the argument across more systems. Fix ownership first.
A strong fit still needs named owners. Assign one person each for routing rules, adapters, feature flags, and synchronization jobs before the first slice ships. Without that, transitional code becomes permanent because deleting it is nobody's job.
For a broader decision between rebuilding, refactoring, or moving platform, run your situation against a structured comparison of legacy rebuild, refactor, and replatform options first. Choose strangler fig because it wins on risk and time to value, not because it's fashionable.
Use a concrete example. Say you run a SaaS billing monolith, and invoicing is the first candidate. The flow below shows the shape of the work before the detailed steps.

The discipline is consistent across systems. Thoughtworks' guide to the Strangler Fig pattern for legacy modernization identifies seven mechanics, establish the boundaries of the system being replaced, divide it into thin slices, introduce an indirection layer, build replacement components, route traffic to those components, retire the old components, and repeat the cycle. A thin slice must be small enough to replace incrementally but substantial enough to deliver business value.
The video below walks through the routing mechanics visually, which helps when non-engineers need to understand why the facade matters.
Practical rule: One slice proving itself in production teaches you more than five slices designed perfectly on a whiteboard.
The common mistakes are moving too many slices at once and treating rollback as a routing change after the new system has accepted writes. Once writes move, rollback also means bringing those writes back. Plan that before you need it, and rehearse it while the stakes are low.
The routing facade gets the attention, but data breaks migrations. Fowler's Strangler Fig Application guidance emphasizes that strangler modernization can evolve a monolith without requiring microservices, while database evolution remains a separate challenge. A safe implementation assigns an explicit system of record for each migrated aggregate and avoids uncontrolled dual writes.
Start with the facade anyway, because it becomes production infrastructure the day traffic passes through it. It decides which system handles each request, so it must provide observability, authentication and authorization continuity, timeout and retry policies, correlation IDs, rate limiting, and deterministic rollback. Without those, it becomes a bottleneck or single point of failure that takes both systems down together.
| Component | Job during coexistence | What breaks without it |
|---|---|---|
| Routing facade (API gateway or proxy) | Sends each request to legacy or new component | No clean rollback path and no single view of traffic |
| System of record per business object | Defines which system owns each piece of data | Conflicting customer, order or billing state |
| Anti-corruption layer | Translates between legacy and new data models | Legacy concepts leak into the new services |
| Transactional outbox or CDC pipeline | Publishes changes reliably between systems | Lost or duplicated updates during dual writes |
| Idempotent consumers and replayable events | Make retries safe | Duplicate charges, orders or records after partial failures |
| Reconciliation reports | Compare legacy and new results over time | Drift stays hidden until a customer reports it |
Assign one explicit system of record for each migrated business object and write it down where engineers, support, and finance can see it. If an invoice lives in the new system, the legacy system reads it or receives a synchronized copy. It doesn't invent its own version.
Where dual writes are unavoidable, use a transactional outbox or change-data-capture pipeline, idempotent consumers, replayable events, and reconciliation reports with a defined consistency window. Retries and partial failures will happen. Your design decides whether they create duplicate charges or a boring log entry.
An anti-corruption layer handles a different problem. Legacy and new models often use the same word for different things. Translate at the boundary so old meanings don't leak into the new system and rebuild the mess you were trying to leave.
Choose slices by data ownership, not code convenience. Extracting a service while its tables stay tightly coupled to the monolith produces a distributed monolith, with network failures added to your existing problems. A sound data migration architecture is therefore part of the slice decision, not an afterthought once the service exists.
Coexistence needs a dashboard, not hope. Agree the thresholds that pause or reverse a traffic increase before the increase, while nobody is defending a launch date. Review them weekly with a named owner for each slice.
| Signal | Healthy target | What it tells you |
|---|---|---|
| Route-level success rate | At or above the legacy baseline before each traffic increase | Whether the new component is safe to receive more traffic |
| p95 and p99 latency | No regression against the legacy baseline | Slow requests that averages hide |
| Duplicate-event rate | Near zero and explained | Retries or dual writes that are not idempotent |
| Reconciliation exceptions | Falling toward zero across a full business cycle | Hidden data drift between old and new |
| Rollback frequency | Low and falling | Whether the slice is ready for more traffic |
| Traffic still on legacy | Falling with every release | Real progress toward decommissioning |
Watch the tail, not just the average. p95 and p99 latency expose the slow requests customers remember, including any cost added by the extra routing hop. A slice can be functionally correct and still be a worse product.
Treat a growing reconciliation queue as a stop signal. It means old and new don't agree, and more traffic just creates more disagreement faster. These same signals strengthen your wider work on how to improve system reliability, so keep the dashboard after the migration ends.
Most guides assume completion follows naturally once features move. It doesn't. Teams migrate visible features first and postpone batch jobs, reports, integrations, and support procedures. Then the old system stays alive for work nobody sees in a demo.
AWS Prescriptive Guidance on the Strangler Fig pattern highlights data-consistency complexity, and the wider risk is clear. The routing facade can become a bottleneck, and a stalled migration leaves both systems operating indefinitely. You've reduced release risk and increased long-term cost.
The checklist below names the low-visibility work that usually determines whether you can switch the legacy system off.

Ask a harder question for every slice. What evidence proves it's strangled? "The new screen is live" isn't evidence.
| Completion signal | Target to reach | Warning sign |
|---|---|---|
| Traffic ownership | 100% of the domain served by the replacement | Scheduled jobs or clients still calling legacy code |
| Reconciliation drift | Zero unresolved differences across a full business cycle | Exception queue keeps growing |
| Legacy consumers | Removed or repointed to the new route | Undocumented client still calls the old endpoint |
| Rollback limit | Documented, tested and time-boxed | Rollback has never been rehearsed |
| Shutdown date | Approved and owned by a named person | Date moves every quarter |
Check the dependencies that keep legacy code alive. Scheduled jobs, batch integrations, reporting queries, support tools, and undocumented API clients all count as consumers. If one still calls the old path, the slice isn't done, whatever the roadmap says.
Assign one owner each for routing rules, compatibility adapters, feature flags, synchronization jobs, observability, and legacy retirement. Review those owners at every steering meeting. Measure decommissionability, operational load, dependency removal, and total cost, not just percentage of code moved.
If the shutdown date moves every quarter, you don't have a migration plan. You have two products.
Run a go or no-go check on one candidate slice before you commit the program. Pick a business capability with clear customer or revenue value. Don't start with the hardest module just to prove a point.
Work the three stages in order. Transform the capability, coexist with rollback available, then eliminate the old path once traffic and dependencies are gone. That last step is where the savings live, so protect it in the plan.
Senior engineers stay accountable for architecture, data, security, testing, and production quality. AI-assisted tooling speeds up analysis, documentation, test generation, and migration work, but it doesn't lower the engineering standard or own the result. That accountability is the #riteway in practice, extreme ownership with transparent communication.
If your team lacks senior architects in-house, or you want one partner who owns the full result, Rite NRG works on legacy-to-SaaS modernization end to end, from the first slice through decommissioning. Start this week. List your capabilities, pick one slice, and write its exit criteria before anyone writes code.
Don't let another quarter disappear into a rewrite that ships nothing. Visit Rite NRG to map your first strangler slice, set its exit criteria, and agree a retirement date with senior engineers who'll own the result from routing and data through to decommissioning.
/ about the author
Written by the RITE NRG editorial team — the architects, engineers and delivery leads who build and operate AI-era software for our clients.
Strategy & Transformation
A practical, finance-ready framework for comparing AI and modernization investment with the current-state cost, realistic benefits, delivery risk and time to value.
Technology Talent & Teams
A decision-maker's guide to IT partnership models: what each model actually transfers to the partner, what it costs beyond the rate card, and how to match the model to your situation.
AI Consulting & Automation
A practical framework for choosing and deploying transport or logistics AI agents around real exceptions, reliable data and controlled operational authority.
More guidance: all insights articles
Tell us about the system or idea behind this article. We tell you honestly if it is a fit — and what a fixed-scope delivery could look like.