Where do you start with the Strangler Fig pattern?
In the Padua case, 8 modules out of 40 receive 71% of the changes. Replacing only those costs 2,181,060 euros over five years against 2,520,000 for doing nothing, with break-even at month 32. A full rewrite costs less only if everything goes well: with frozen changes and the risk of stopping it reaches 2,515,250 euros.

An electrical supplies distributor in Padova, ninety employees, 38 million euros in revenue, runs a management system written between 2009 and 2011 in ASP.NET Web Forms on .NET Framework 4.8. It has 380,000 lines, 40 modules and a SQL Server database with 410 tables. Five people maintain it, in-house and external, and every change costs almost double what it would cost on a modern application.
The managing director has two quotes on the table. The first proposes rewriting everything from scratch in 24 months. The second proposes touching nothing "as long as it holds". He likes neither, and he is right: they are the two riskiest roads there are, except that one risks now and the other risks later.
There is a third road, and it has a name: the Strangler Fig pattern. You put a facade in front of the old system, you build the new one next to the old one a piece at a time, and every piece that works takes the place of the one it replaces. The old system is not switched off: it is strangled, the way the fig strangles the tree that hosts it.
In this article you will find how it works, how much it costs in euros over five years, and the number that decides where to start: the share of changes that falls in 20% of the modules. You will also find the facade in code, the data knot, the test that tells you whether a piece is ready, and the cases where the pattern does not pay off.
An honest premise. Since 1999 I have been modernizing systems that have been in production for fifteen years, and I built and sold a multi-tenant legal management system. The Padova case is a composite, not a real client, but the numbers are orders of magnitude I have seen many times. The assumptions are written down, and you can replace them with your own.
What is the Strangler Fig pattern?
The name was given by Martin Fowler in 2004, inspired by the strangler figs of the Australian forests. The seed germinates on the high branches of a tree, sends roots toward the ground and grows around the trunk. After a few decades the host tree is dead and the fig stands on its own, with the same shape.
In software the metaphor is precise. The old system stays in production the whole time. The new system grows around it, function after function. At some point the old one is no longer needed and gets switched off without anyone noticing.
The pattern has three moves, always the same.
- Put up a facade. A single entry point in front of the old system, which for now forwards everything as it is. Users see no difference.
- Build a new piece and redirect the traffic. You rewrite one function, put it in production behind the facade and change the rule: that request now goes to the new one.
- Switch off the old piece. When the new one has worked long enough without surprises, the old code for that function is deleted. You repeat with the next function.
It sounds obvious, and that is why it works. Every step is small, can be undone in a minute and brings value right away. A full rewrite does the opposite: it delivers nothing for two years and then asks for a leap in the dark on a Saturday night.
The pattern is not a technology. You can do it with a reverse proxy, with a web application, with a service, and you can even do it inside a desktop program with a bit more effort. What matters is that there is a point where you can decide, request by request, who answers.
Why is a rewrite from scratch not the answer?
When a system is old and painful, the idea of redoing it from the beginning is very appealing. There are four reasons why it usually goes badly, and I have seen all of them.
The old system contains rules that nobody remembers. In fifteen years the code has absorbed hundreds of special cases: the customer who pays at 75 days, the discount that does not apply to cables, the rounding that the accountant demands at the third decimal. Nobody wrote them in a document. They live in the code, and the rewrite loses them until a customer complains.
The old system keeps changing. While the team writes the new one, the business asks for changes to the old one. Either you freeze changes for two years, and the company notices, or you write them twice.
The value arrives at the end. For 18 or 24 months you spend and deliver nothing. If the project stops in the twentieth month, because of a budget change or a change of director, everything has been thrown away.
The leap is a single one. On release day you move every user, every piece of data and every integration in one go. The rollback plan, if there is one, takes back a system that in the meantime has written new data.
| Question | Rewrite from scratch | Strangler Fig |
|---|---|---|
| When does the first value arrive? | At the end, after 18 - 24 months | After 3 - 4 months, with the first module |
| What happens to the requested changes? | Frozen or written twice | They are made in the new system, for the modules already migrated |
| How much is lost if the budget stops? | Almost everything | Nothing: the migrated modules stay in production |
| How big is the release? | A single leap | One module at a time, reversible |
| Who discovers the hidden rules? | The users, after the release | The tests on the old system, before the replacement |
| How much does it cost if everything goes well? | Less, because you avoid the facade and the coexistence | More: in the Padova case 16% |
The last row holds a fact that people who sell this pattern do not always tell you: if the rewrite goes well, it costs less. You do not have to build the facade, you do not have to make two systems coexist, you do not have to maintain two versions of the data. The point is the probability that it goes well, and how much it costs when it does not. We measure it further down, with numbers.
How much does the legacy system cost if you do nothing?
Before comparing the roads you have to put a price on the current state, because "doing nothing" is not free. It costs every month, and the bill is the one that almost nobody writes down. The full method is in the guide to the cost of legacy software. Here I use its shortest form.
For the Padova company there are four assumptions.
- Changes requested every year: 600 days, measured at "normal" speed, meaning what they would cost on a modern, well-tested application.
- Legacy multiplier: 1.8. Every change on the old system costs 80% more, because of orientation time, regression risk and manual testing. It is the most debatable assumption, and further down I vary it.
- Average rate: 450 euros per day, between in-house and external staff.
- Infrastructure: 18,000 euros a year for the Windows servers, licenses and backup of the old system, 9,000 for an equivalent modern infrastructure.
The yearly cost of the system as it is today:
600 days × 1.8 × 450 euros = 486,000 euros, plus 18,000 of infrastructure, that is 504,000 euros a year. Over five years that is 2,520,000 euros.
The number makes an impression, and it should. But be careful not to read it as "we are throwing away 2.5 million": part of that spending is the normal cost of changing software, and it would appear with a new system too. What the new system removes is the difference between 1.8 and 1.0, that is 216,000 euros a year of pure friction, plus 9,000 of infrastructure.
A legacy system does not cost because it is old. It costs because every change pays an 80% tax, and pays it every time.
What is the number that decides where to start?
If the tax is paid on changes, the question becomes where the changes fall. The system has 40 modules, but the requests are not spread evenly. Almost never are they.
The deciding number is this: the share of the changes of the last twelve months that falls in 20% of the modules. You sort the modules by number of interventions, take the top fifth, and look at how much of the total is in there.
In Padova I measured it like this. Twelve months of history, 1,240 interventions between fixes and change requests, each attributed to a module. The eight most touched modules, 20% of forty, receive 880 interventions: 71%.

This number serves three decisions.
- Whether it pays off. Above 50% the pattern pays back quickly, because migrating a few modules is enough to remove most of the tax. Below 32%, in my model, it does not pay back even in five years: the pain is spread everywhere and another method is better.
- Where to start. You start from the modules where the changes fall, not from the easiest ones and not from the ugliest ones. Further down I explain why starting from the easy ones costs 88,658 euros more, for the same goal.
- Where to stop. After the eight hot modules the old system can stay alive for several more years, at low cost, with the thirty almost still modules. Stopping is a legitimate choice, and the pattern is the only one that allows it.
How to measure it in an afternoon
If the code is in Git and the folders match the modules, one line on the history is enough. This one counts the files touched by the commits of the last twelve months, by first-level folder under src:
git log --since="12 months ago" --name-only --pretty=format: -- src \
| awk -F/ 'NF>2 {print $2}' \
| sort | uniq -c | sort -rn | head -20It is a rough measure: it counts files and not interventions, and a big commit weighs the same as a small one. For a decision worth hundreds of thousands of euros it should be refined with the ticket log, which tells you which requests were fixes and which were new features. But the order of the modules rarely changes. If the top fifth of the ranking contains more than half of the touches, you already have the answer.
One warning. The history tells you where changes were made, not where you would like to make them. If a module is so fragile that nobody dares to touch it, it will appear at the bottom of the ranking out of fear and not out of stability. Ask the team which modules are "the ones nobody likes to touch": they are often the first to replace, and the history does not show them.
How much does it really cost over five years?
I line up five roads on the same case and the same horizon. The common assumptions are the ones above. The specific ones are eight.
- Full migration: 1,100 days for all 40 modules.
- Hot modules: the eight modules with 71% of the changes cost 480 days, 60 each, because they are the biggest. The remaining thirty-two cost 620, about 19 each.
- Facade: 40 days, done in the first year.
- Cost of the new system: a change on the new system costs 1.0 and not 1.8.
- Year 1: changes still cost as before, because the first module reaches production at the end of the year.
- Rewrite from scratch: 1,650 days, that is 50% more than the module-by-module migration, because nothing is reused. Two years of work, during which only 25% of the requested changes are made. Twenty thousand euros of parallel running in the second year.
- Rewrite risk: the probability that it stops before the finish line is 30%. It is a professional opinion, and I discuss it below.
- Value of the frozen changes: 450 euros for each day of work not done, that is only the development cost and not the benefit they brought. It is a prudent estimate.
Here are the five-year totals, in euros.
| Road | Year 1 | Year 2 | Year 3 | Year 4 | Year 5 | Total |
|---|---|---|---|---|---|---|
| Do nothing | 504,000 | 504,000 | 504,000 | 504,000 | 504,000 | 2,520,000 |
| Strangler, hot modules and then the rest | 742,500 | 499,140 | 467,820 | 279,000 | 279,000 | 2,267,460 |
| Strangler, hot modules only | 742,500 | 359,640 | 359,640 | 359,640 | 359,640 | 2,181,060 |
| Strangler, easy modules first | 742,500 | 558,245 | 497,373 | 279,000 | 279,000 | 2,356,118 |
| Rewrite, if everything goes well | 515,250 | 535,250 | 279,000 | 279,000 | 279,000 | 1,887,500 |
| Rewrite, with freeze and risk | 1,887,500 + 405,000 of frozen changes + 222,750 of expected risk | 2,515,250 | ||||

I read the table with you, because it says less obvious things than someone looking for a single answer expects.
The rewrite, if everything goes well, wins. 1,887,500 euros against 2,181,060: 293,560 euros less. I say it openly because whoever recommends the Strangler Fig without admitting it is selling. If you are certain that the rewrite succeeds on time, over five years it costs less.
The rewrite with the freeze and the risk no longer wins. To the 1,887,500 you add 405,000 euros of changes that you did not make for two years, and 222,750 euros of expected risk, that is a 30% probability of losing the 742,500 euros spent. The total exceeds that of doing nothing. The risk and the freeze are what separates the quote from reality.
Strangler on the hot modules alone saves 338,940 euros compared with doing nothing. The first year costs more than any other, 238,500 euros more, because you pay for the migration and keep paying for the old system. From the second year it saves 144,360 euros every year. The break-even arrives around the thirty-second month.
Starting from the easy modules costs 88,658 euros more. The goal is the same, all modules migrated, but the "easy first" road ends at 2,356,118 euros and the "hot and then the rest" one at 2,267,460. The easy modules remove only their share of the tax, and the share is low because nobody touches them. The relief arrives late. The team, which expected improvements right away, loses morale in the second year.
The line you cannot skip is the last one: the pattern is not the cheapest in absolute terms, it is the cheapest one you can trust. It costs 16% more than the perfect rewrite (2,181,060 euros against 1,887,500) and 13% less than the one with freeze and risk (against 2,515,250), and it does not require you to believe in any forecast.
The model in code
The calculation fits in a few lines, and it is worth having it in executable form to change the assumptions to those of your company. This is the core, the part that estimates the cost of changes in one year given the share already moved to the new system:
record Ipotesi(double Tariffa, int GiornateModifiche, double MoltiplicatoreLegacy);
static double CostoModifiche(Ipotesi h, double quotaSulNuovo) =>
h.GiornateModifiche * h.Tariffa *
(quotaSulNuovo * 1.0 + (1 - quotaSulNuovo) * h.MoltiplicatoreLegacy);
var padova = new Ipotesi(450, 600, 1.8);
Console.WriteLine(CostoModifiche(padova, 0.0)); // 486000, everything on the old system
Console.WriteLine(CostoModifiche(padova, 0.71)); // 332640, 71% on the new oneThe rest of the model is a sum per year: cost of changes, migration days times the rate, old and new infrastructure. Nothing else is needed. If in a meeting someone objects that the multiplier is too high, you change the number and look at the total. It is a discussion that finally has an object.
How fragile are these numbers?
Very, and it is better to know it. The two assumptions that move everything are the concentration of changes and the legacy multiplier. I varied them one at a time, on the "hot modules only" road, and kept everything else fixed.
| Share of changes in 20% of the modules | Five-year saving compared with doing nothing | Reading |
|---|---|---|
| 30% | - 15,300 euros | Costs more than doing nothing |
| 45% | 114,300 euros | Pays back little, high risk |
| 60% | 243,900 euros | Pays back, fine |
| 71% | 338,940 euros | The Padova case |
| 85% | 459,900 euros | Pays back clearly |
| Legacy multiplier | Yearly cost of doing nothing | Five-year saving |
|---|---|---|
| 1.2 | 342,000 euros | - 121,140 euros |
| 1.4 | 396,000 euros | 32,220 euros |
| 1.8 | 504,000 euros | 338,940 euros |
| 2.2 | 612,000 euros | 645,660 euros |
Two clear thresholds. Below a concentration of 32% the pattern does not pay back, because there is no place where the tax is concentrated. Below a multiplier of 1.4 it does not pay back either, because the tax is too low to justify the migration. If your legacy is healthy enough to cost only 20% more, it should probably be left where it is and looked after.
The multiplier is the hardest number to measure. The way I do it is to compare the team's estimates with the real times on two or three interventions of the same type, one on the old system and one on a recent application of the same company. If there is no comparison, I ask them to count the hours spent understanding the code before writing the first line. Often it is more than half.
How do you build the facade?
The facade is the only piece you write right away. It is a reverse proxy in front of the old system, and for a .NET web application the simplest choice is YARP, Microsoft's reverse proxy, which is a library inside a normal ASP.NET Core application. Forty days to put it in production is a prudent assumption: the technical part takes much less, the rest is for tests, certificates and monitoring.
On the first day the facade must do only one thing: forward everything to the old system. The two routing rules are these, in the appsettings.json file:
{
"ReverseProxy": {
"Routes": {
"ordini-nuovo": {
"ClusterId": "nuovo",
"Order": 1,
"Match": { "Path": "/ordini/{**resto}" }
},
"tutto-il-resto": {
"ClusterId": "legacy",
"Order": 100,
"Match": { "Path": "{**resto}" }
}
},
"Clusters": {
"nuovo": { "Destinations": { "d1": { "Address": "http://nuovo.interno:8080/" } } },
"legacy": { "Destinations": { "d1": { "Address": "http://legacy.interno/" } } }
}
}
}And the program that starts it is four lines:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
var app = builder.Build();
app.MapReverseProxy();
app.Run();The rule with the lowest Order wins. When the orders module is ready you turn on the first one, and all the traffic that starts with /ordini goes to the new system. To go back you remove the line and restart the facade: one minute, without releasing the old system.

Three ways to turn on a module without fear
Moving all the users together is exactly the kind of leap the pattern wants to avoid. That is why turning on a module has three steps, and each can be undone.
- First step: only the team. One more rule on the facade, which matches an HTTP header or a cookie and sends only whoever carries it to the new system. The team uses the new module for a few days on real work, with real data.
- Second step: a pilot group. A branch, a department, five users who agree to work on the new system for two weeks. They have a phone number to call, and going back to the old system is immediate.
- Third step: everyone, with the old system on. The path moves to the new system for everyone, but the old code stays in production for another month. If something unexpected happens, you put the previous rule back.
Only after a month without returns do you delete the old code. On that day, and not before, the module is really replaced. The cost of keeping two versions on for a month is small, and the peace of mind is worth it.
What is the real problem: the data?
Whoever has tried it says that the hard part is not the code, it is the database. They are right. The facade routes requests, but the data is only one, and two applications writing to the same tables without a rule produce corrupted data within a week.
There are three possible roads, in order of difficulty.
Shared database, with a single writer per table
This is the road I recommend for starting, and it is the one used in Padova. The old and the new system read and write on the same database, but every table has a single owner. When the orders module moves to the new system, the orders tables also move to the new system as writer. The old one only reads them, and if it needs to modify them it calls the new one.
The rule is enforced with database permissions: the old system's user loses the write right on those tables on the day of switching on. If a forgotten function tries to write, it fails immediately and loudly, and not silently after three months.
Translation layer between the two worlds
The old schema has names, types and conventions that you would not want to carry into the new one: text columns that contain numbers, dates saved as strings, an order status encoded with three letters. You put an anti-corruption layer in the new system, which translates from the old model to a clean model and back. The rest of the new system never sees the old schema.
It is a boring and precious piece of code. It has a single task, and when the old system is switched off it is deleted together with it.
Separate databases and replication
The new system has its own database, and the data flows through replication or events. It is the cleanest road and the most expensive, and it is needed almost only when the old schema is truly untouchable or the new system has to run in another environment, for example in the cloud. The window in which the two databases can diverge is the riskiest part of the whole project, and to start with I do not recommend it.
The criterion is simple: the simplest road that keeps a single writer for every piece of data. If two modules have to write to the same table and you cannot separate them, they are the same module and you migrate them together.
Access and session
The second knot is the user. Whoever has logged in on the old system must not do it again to open a page served by the new one. For ASP.NET applications on .NET Framework there is a Microsoft library, System.Web Adapters, designed for incremental migration: it lets the new system reuse the authentication and, if needed, even the session of the old one, by calling it to find out who the user is.
If the old system is on another technology, the solution is less elegant and safer: the login stays in the old system until the last module, the facade adds a signed header with the user's identity, and the new system trusts only requests that come from the facade. In the new system you do not rewrite the password until you migrate the login, which is almost always the last module.
How do you choose the first module?
The concentration number tells you where the changes fall. It is not enough, because a hot module can also be the most tangled with the rest, and then the first piece becomes a battle. I use a grid with four criteria, each from 1 to 5.
| Criterion | Question | A high score means |
|---|---|---|
| Concentration | How many of the changes of the last twelve months fall here? | Many, so a lot to gain |
| Boundaries | How many other modules call it or write its data? | Few, so it comes apart cleanly |
| Tests | Are there ways to verify that the behavior is the same? | Yes, so the risk is measurable |
| Visibility | Will users notice if it works better? | Yes, so trust grows quickly |
The first module is not the one with the maximum score in concentration. It is the one with the highest total score, with concentration weighing double. A first piece with sharp boundaries, possible tests and a good visible benefit buys the trust the project will need over the following thirty months.
In Padova the first module was Preventivi (quotes): seventh by interventions with 48 out of 1,240, so not the hottest. But it was detached from the rest, it had documented calculation rules and the sales people were happy to have a page that did not freeze. It closed in 14 weeks. The second was Ordini (orders), the most touched, with 214 interventions: it cost 118 days, and in six months it removed 17% of the tax by itself.
What to leave for last
There are three kinds of modules that are better touched last, even if they are hot.
- The central calculation engine. Prices, commissions, accounting. It has more hidden rules than all the rest, and it is better to have it surrounded by tests before rewriting it. When its turn comes the team already has a year of experience on the system.
- The login. All the modules depend on it. It moves after the rest is migrated, because earlier it would move the access problem onto every new module.
- Rigid third-party integrations. The link with the bank, with the courier, with electronic invoicing. If the third party does not change, the old code that talks to it can stay alive for years without doing damage.
How do you know a new piece is ready?
The real risk of the pattern is replacing an old piece with a new one that behaves differently, without anyone noticing until it is too late. Three defenses, in order.
Characterization tests on the old system
Before writing the new one, you write tests on the old one that record what it does, not what it should do. It is the technique that Michael Feathers describes in Working Effectively with Legacy Code: you give real inputs, you save the current output and that result becomes the specification. If the old system calculates a discount in a bizarre way, the test records it, and the new one will have to do the same or the difference will have to be decided by the business.
You also need a few hand-picked cases, those of the customers with the strange rules. About thirty cases with real, anonymized data are worth more than a thousand generated tests.
Parallel comparison
For read-only requests you can have the new system answer in the shadows: the facade forwards the request to the old one, which answers the user, and in parallel sends it to the new one, discarding the response but comparing it with the other. The differences end up in a log. After two weeks you know how many responses diverge, on which paths and with what kind of difference.
The exit rule I use is a threshold: below 0.1% of unexplained divergences the module can move to the pilot group. Every explained divergence, for example a wrong rounding in the old system that the new one corrects, is filed as a decision.
The minute of the rollback
Before turning on a module, the team switches it off on purpose, in a test environment, and checks that the rollback works: the routing rule is removed, the old system answers, the data written in the meantime stays consistent. A rollback never tried is a promise, not a plan. The test is done once per module, takes half an hour and has saved more projects than any other practice.

How long does it take and who is needed?
For a system like the one in Padova the realistic schedule has four phases.
| Phase | Duration | What happens |
|---|---|---|
| Measurement | 2 - 3 weeks | Map of the modules, concentration of changes, multiplier, dependencies and cost of each module |
| Facade and first module | 3 - 4 months | Reverse proxy in production, characterization tests, first small module turned on with the three steps |
| Hot modules | 9 - 14 months | The eight modules with 71% of the changes, one every 6 - 8 weeks on average |
| Tail and shutdown | 12 - 18 months, optional | The thirty-two almost still modules, the login, the integrations, the shutdown of the old system |
The cost figures per module that I use as a starting point are these, in days: a small, detached module 8 - 15, a medium one with some dependencies 25 - 45, a central module 60 - 120. For every module I add 15% for coexistence, that is translation layer, characterization tests and shadow comparison.
The minimum team is three people. An architect or technical lead who decides the order of the modules, keeps the boundaries and says no to returns to the old system. Two developers who write the new system. You also need, part time, a business person who knows the rules and does acceptance testing, and someone from the old team who knows where the traps are.
If you do it with an in-house team, the most common risk is that the team remains the only one maintaining the old system while writing the new one, and works at double load. The load on the old system must be reduced, or you hire. If you do it with a supplier, the rules of the guide on how to decide between keeping, porting and rewriting apply: repository in the client's account, measured handover, payment in phases.
What mistakes make a Strangler project fail?
I have seen seven recur, and almost always they are mistakes of method and not of technology.
- Starting from the easy modules. The team gets quick and useless results. The director looks at the numbers at the end of the year and sees no saving, because the easy modules do not touch the tax.
- Not setting a deadline for the old system. The migrated modules are left on "for safety", the old code is never deleted and you end up maintaining two systems. Every module has a written deletion date, usually thirty days after turning on.
- Two writers on the same table. It works for three weeks and then the data diverges, in a way no test had foreseen. It is the mistake that costs the most, and it is avoided with database permissions.
- Rewriting "better" while migrating. You take advantage of the move to change the rules, add features, redesign the screens. The comparison with the old system becomes impossible. First you move it the same, then you improve.
- The facade that is too smart. The proxy starts to have business logic, transformations, special caches. It becomes the new monolith. It must only route, and at most authenticate.
- No metrics. Nobody knows what each moved module gains. The share of changes on the new system, the average time per change and the number of regressions must be watched every month, with the starting value written down before beginning.
- Only the architect knows how it works. If the person who holds the design leaves, the pattern degenerates into a pile of meaningless services. The decisions must be written down, one page per module.
When does the Strangler Fig not pay off?
There are four situations in which I recommend another road, and saying so is part of the job.
- The changes are scattered. If no group of modules exceeds 32% of the changes, there is nowhere to concentrate the effort. The pain is in the architecture and not in the modules, and another intervention is needed: often a database cleanup or the introduction of tests, more than a migration.
- The system is small. Below 30,000 lines and a dozen modules, the facade and the coexistence cost more than the rewrite. You redo it, with characterization tests so as not to lose the rules.
- There is no seam. A monolithic desktop program, for example in Windows Forms or VB6, has no point where a facade can be inserted. It is not impossible: you can host the new system inside the old one with web controls or with a local service, as I describe in the case of the SCADA system in VB6. But it is another trade, and slower.
- The multiplier is low. If your legacy costs only 20 - 30% more than a modern system, the migration does not pay back. You look after it, you add tests and you leave it where it is.
For the cases with an interface to bring to the web, the guide to Blazor and enterprise migration says when to move away from Web Forms and WPF, and the one on Razor Pages, MVC and Blazor helps you choose the technology for the new modules. If instead the new system has to serve several customers with the same installation, you first need the guide to multi-tenant architecture in .NET.
What do you do in the first thirty days?
A plan you can start on Monday, without asking for a big budget.
- Week 1: the map. List the modules, give each one an owner and a count of the interventions of the last twelve months. Calculate the share of the top fifth. If it is below 32%, stop and rethink the road.
- Week 2: the price of friction. Estimate the multiplier with three comparable interventions. Write down the model assumptions and have the yearly cost of doing nothing calculated. Put the number in front of whoever decides the budget.
- Week 3: the boundaries. For the eight hottest modules, draw who calls them and which tables they write. Assign each table a single future owner. Give the score with the four-criteria grid.
- Week 4: the first module and the budget. Choose the first module, estimate the days and the facade, and ask for the budget for the first four months only. Not for the thirty.
At the end of the month you have three things you did not have before: a concentration number, a yearly cost of friction and a small, reversible first step. With these three, the meeting with management changes subject: you no longer discuss whether to modernize, but where to start and how much you are willing to spend for the first four months.
What would have happened in Padova?
I come back to the electrical supplies distributor. The managing director had two quotes, the rewrite from scratch and the wait. Nobody had told him there was a number to measure before choosing.
With the calculation in hand he would have seen that doing nothing cost 504,000 euros a year, and that 71% of the changes fell in eight modules out of forty. He would have seen that the rewrite, if it went well, cost 293,560 euros less than the other road, and that with the freeze of changes and the risk of stopping it cost as much as doing nothing.
He would have chosen to start with 234,000 euros, the facade plus the eight hot modules, with a break-even at the thirty-second month and the possibility of stopping at any moment. It is not the cheapest road in absolute terms. It is the only one in which, at every step, he can say stop without having lost everything.
If you have a similar system, written years ago by someone who is no longer there, and you want to know how concentrated your pain is, the path starts with legacy software modernization. To work out the hidden costs you will find the guide to the cost of legacy software, and if you need someone to look at the system with you there is software consulting.
In five lines. Measure the share of changes in 20% of the modules, and if it is below 32% do not use the pattern. Put up a facade before writing a line of new code. Start from the modules where the changes fall, not from the easy ones. A single writer for every table, always. Every module has a tested rollback and a deletion date for the old code.
Frequently asked questions
It is a migration method in which a facade is placed in front of the old system and one function at a time is replaced with a new one, redirecting traffic module by module. The old system stays in production until it is no longer needed. The name comes from the strangler fig, which grows around a tree until it takes its place. Martin Fowler described it in 2004.
If the rewrite succeeds on time it costs less: in this article's case 1,887,500 euros over five years against 2,181,060. But with two years of frozen changes and a 30% chance of stopping, the rewrite reaches 2,515,250 euros, more than doing nothing. The Strangler costs 16% more than a perfect rewrite and 13% less than one with freeze and risk, and it can be stopped at any time.
With the modules where the changes fall, not the easiest ones. Sort the modules by number of changes over the last twelve months and look at the share of the top 20%. In the case described, eight modules out of forty receive 71% of the changes. The first module is chosen with four criteria: concentration of changes, clean boundaries, testability and visibility to users.
When changes are scattered and no group of modules exceeds 32% of the total, when the system is small (under 30,000 lines), when the legacy costs only 20-30% more than a modern system, and when there is no seam to insert the facade, as in a monolithic desktop program. In those cases it is better to repair, tidy the data or rewrite.
The simplest route is a shared database with a single writer per table: when a module moves to the new system its tables move too, and the old system only reads them. Database permissions enforce it. An anti-corruption layer translates between the old schema and a clean model. Separate databases with replication are only needed when the old schema cannot be touched.
For a system of 380,000 lines and 40 modules: 2-3 weeks of measurement, 3-4 months for the facade and first module, 9-14 months for the eight hot modules and 12-18 months, optionally, for the tail and switching off the old system. Cost break-even arrives around month 32. The minimum team is three people: an architect and two developers.
