
Key takeaways
• Legacy is a cost problem, not an age problem. Code becomes legacy the day it gets risky and expensive to change, whether it shipped in 2010 or last year.
• You have seven moves, not two. Encapsulate, rehost, replatform, refactor, rearchitect, rebuild, replace. Most owners jump to “rewrite” and pick the most expensive, riskiest one by default.
• The full rewrite is usually the trap. It freezes your roadmap for a year while competitors ship. Reach for it only when the platform itself is dead.
• The Strangler Fig lets you modernize live. Route traffic to new code one slice at a time, with the old system serving users the whole way, so there is no big-bang cutover.
• Start with a code audit, not a rewrite. A one-to-two-week audit tells you which modules to fix, replace, or leave alone before anyone writes a line.
Updated October 2026: runtimes that lost support in 2026 (.NET 8 and 9, Node.js 20, Python 3.10), EU Cyber Resilience Act reporting from September 2026, and the current AI modernization tools (AWS Transform, GitHub Copilot app modernization).
Your product still works. That is exactly why the legacy code inside it is dangerous. Every quarter it costs a little more to change, security patches get harder to apply, and the one engineer who understands the billing module is updating their CV. Legacy code modernization is how you climb out of that corner without betting the company on a rewrite: you pick the cheapest of seven moves that fixes the real problem, and most of the time that is not a rewrite.
Fora Soft is a software development company with a 50+ person in-house team that has delivered 250+ projects since 2005, and we still run and extend systems we first wrote more than a decade ago. So this playbook is the decision process we actually use with clients, not a vendor brochure. Most of those engagements start with our code audit, which names the file, the line and the fix for every issue before anyone picks a strategy. We will be straight about when to leave code alone, when a small refactor pays for itself, and when a rewrite is the move that quietly kills a product.
Why Fora Soft wrote this modernization playbook
Most legacy-code advice comes from two places: enterprise vendors who want to sell you a cloud platform, and consultancies who bill by the year. Neither has to live with the result. We do. On several products we have been the same team for eight, ten, twelve years running, which means every shortcut we ever took eventually came back to our own desk.
That long-run seat changes the advice. We have modernized a 720,000-track music-recognition platform for professional DJs without taking it offline, been the sole team on a HIPAA video-surveillance system used by 770+ US organizations for a decade, and talked more than one founder out of a rewrite that would have burned a year for no new user value. The published depth behind that work lives in our engineering Learn hub.
The pattern we see: teams treat “the code is old” as the problem and “rewrite it” as the answer. Both are usually wrong. The rest of this guide is how to think about it properly, with the numbers to back each call.
Not sure your legacy code is worth saving?
Book a 30-minute call and we will tell you honestly whether to refactor, strangle, or replace it — before anyone quotes you a rewrite.
What is legacy code modernization?
Legacy code modernization is the work of updating old software — its code, its platform, or its architecture — so it costs less to run, carries less risk, and can take on new features again. It runs on a spectrum, from a light cleanup of the code you keep all the way to retiring the system and adopting something new. When the work covers the whole product rather than one codebase, people usually call it legacy system modernization; the decisions are the same.
Two definitions of “legacy” are worth separating. The engineering one, from Michael Feathers’ book Working Effectively with Legacy Code, is blunt: legacy code is code without tests, because without tests you cannot change it safely. The business one is about money: code is legacy once it is costly or risky to change, no matter how new it looks. A React app from last year with zero tests and a departed author is legacy. A boring, well-tested C# service from 2014 might not be.
Gartner frames the choices as seven options, ordered by how much they cost and how much they disrupt. Figure 1 lays them out so you can see the full menu before you pick.

Figure 1. The seven modernization options, cheapest and least disruptive on the left, most expensive and riskiest on the right.
What legacy code actually costs you
The bill shows up in four places, and only one of them is obvious. First, the direct tax: McKinsey’s 2020 tech-debt study found CIOs estimate technical debt at 20–40% of the value of their whole technology estate, and teams pay an extra 10–20% on top of any project just to work around the debt in the code they touch. A 2022 McKinsey analysis of 220 companies found that firms in the top 20% for managing tech debt grew revenue 20% faster than firms in the bottom 20%. The public sector shows where neglect ends up: the US Government Accountability Office reported in July 2025 (GAO-25-107795) that federal agencies spend about 80% of their $100+ billion annual IT budget on operating and maintaining existing systems, and that only 3 of the 10 critical legacy systems it flagged in 2019 had been modernized by February 2025.
Second, the hiring tax. When your stack is a dead framework, you are recruiting for skills the market has moved on from, and you pay a premium for the few people who still have them. Third, the security tax: unsupported runtimes stop getting patches, so known vulnerabilities simply stay open. Fourth, the opportunity tax, the quiet one that kills companies. Every feature takes longer because the code fights back, so you ship slower than the competitor who modernized last year.
That last one compounds. The longer untouched legacy code sits, the more each new feature costs, because the mess grows faster than the codebase. Figure 2 shows the shape of it, and why the cheapest time to act is usually now.

Figure 2. Let debt grow and the cost of every change climbs; modernizing early resets the slope.
If you want a number before you commit, get a code audit first. It maps the system, flags the modules that are actually dangerous, and turns “the code is bad” into a costed list of what to fix and what to leave.
Which runtimes became legacy in 2026?
Code turns legacy overnight when its runtime stops getting security patches, whatever its quality. In 2026 that happened to several of the most common stacks, so if your product runs on any row below, you now carry the security tax described above. Dates are from each vendor’s official lifecycle page, checked in October 2026.
| Runtime | End of support | What it means for you |
|---|---|---|
| .NET 8 (LTS) and .NET 9 (STS) | November 10, 2026 | Both lose patches on the same day after Microsoft extended STS support to 24 months in 2025. Target .NET 10, the current LTS. |
| Node.js 20 | April 30, 2026 | End of life per the Node.js release schedule; cloud platforms are dropping it from their runtimes. Move to Node.js 22 or 24. |
| Python 3.10 | October 1, 2026 | End of life per the Python developer guide; no more security fixes. Python 3.11 is supported until October 2027. |
| Windows Server 2012 / 2012 R2 | October 13, 2026 | The third and final year of paid Extended Security Updates ended, per Microsoft’s lifecycle page. Rehost or replatform now. |
| Windows 10 | October 14, 2025 | Free support ended a year ago and only paid Extended Security Updates remain (Microsoft); desktop clients and kiosks built for it need a plan. |
Regulation raises the stakes for anyone selling software in Europe. Since September 11, 2026, the EU Cyber Resilience Act requires manufacturers of products with digital elements to report actively exploited vulnerabilities to ENISA within 24 hours (early warning), with a fuller notification within 72 hours and a final report within 14 days of a fix; the full product-security rules follow in December 2027. A product on an unpatched runtime is hard to defend under that regime, which makes end of support a business deadline, not just an engineering one.
The seven ways to modernize legacy code
Here is the full menu in plain words, cheapest first. Read it once before you decide anything, because the right answer is often two or three steps to the left of “rewrite.”
1. Encapsulate. Leave the old code running and wrap it behind a clean API, so new systems talk to the wrapper instead of the mess. Cheapest, least risky, buys you time.
2. Rehost. Lift-and-shift the same code to new infrastructure, for example off an aging on-prem box onto a cloud VM. No code change, lower hosting risk.
3. Replatform. Move it and make small, safe tweaks to fit the new platform, like swapping a self-managed database for a managed one. Same behaviour, modest effort.
4. Refactor. Improve the internal structure of the code you keep, without changing what it does. Add tests, break up the god-class, kill the dead paths.
5. Rearchitect. Restructure the code into new shapes, for example splitting a monolith into services, so it can scale and change independently.
6. Rebuild. Rewrite the component from scratch, keeping its scope. The big one people reach for first and should reach for last.
7. Replace. Retire the system entirely and adopt a different product that already does the job. Sometimes the honest, cheapest answer.
Can you modernize a legacy system without rewriting it?
Yes. Most legacy systems can be modernized without rewriting the source code. Five of the seven options keep the code you have: encapsulate it behind an API, rehost or replatform it onto supported infrastructure, refactor it in place behind tests, or replace one commodity module at a time while the core keeps running. Even when parts must be rebuilt, the Strangler Fig rebuilds them one slice at a time instead of all at once.
- Runtime out of support, logic healthy: rehost or replatform. The code moves, the business rules stay untouched.
- New systems need to talk to it: encapsulate. A thin API wrapper lets mobile apps, partners or AI agents use the old system without changing it.
- Changes are slow and scary: refactor in small steps behind characterization tests (see the step-by-step below).
- One part is commodity: replace just that part, for example auth or billing, and keep the differentiating code.
A rewrite is the exception, reserved for a platform with no upgrade path. If you are not sure which bucket your system falls into, that is exactly the question a code audit answers in one to two weeks.
Refactor: fix the code you keep
Refactoring changes how code is written without changing what it does. It is the default for a system that still earns its keep and runs on a supported stack, but has grown tangled. You wrap the risky module in tests, then clean it in small, reversible steps: rename the confusing things, split the 900-line function, delete the code no path reaches. Users notice nothing except that the next feature ships faster.
The discipline matters more than the tooling. Refactor behind tests, ship daily, never mix a refactor with a behaviour change in the same commit. If you want the full method in plain language, we wrote it up separately: code refactoring, when and why.
How to refactor legacy code safely, step by step
To refactor legacy code safely, first pin down what it does today with characterization tests, then change it in small, reversible commits that never mix cleanup with new behaviour. The sequence below follows the legacy code change algorithm from Michael Feathers’ Working Effectively with Legacy Code, the method we use on client systems.
- Identify change points. List the exact files and functions the next business change has to touch. Refactor there, not everywhere.
- Find test points. Locate where you can observe the code’s output: a return value, a database row, an API response, a log line.
- Break dependencies. Introduce seams so the code can run under test: extract an interface, inject the clock or the database, wrap the static call.
- Write characterization tests. Record what the code does now, bugs included, and assert on it. These tests protect behaviour; they do not judge it.
- Change and refactor in small commits. Rename, extract, split and delete dead paths one step at a time, run the tests after each, and ship daily behind a feature flag where the change is risky.
New code that the old module needs goes in a fresh, tested function the legacy code calls (Feathers calls this “sprout method”), so the untested mass never grows. AI assistants now write first drafts of characterization tests quickly; we still review every one, a practice we describe in how we use AI for QA without creating technical debt.
Reach for refactoring when: the system still fits the business, the platform is supported, and the pain is internal — slow changes and scary deploys — rather than a dead runtime.
Replatform and rehost: move it, mostly as-is
Sometimes the code is fine and the ground under it is the problem: an unsupported OS, a database version past end-of-life, a data centre you want to leave. Rehosting lifts the same code onto new infrastructure. Replatforming does the same but with small, deliberate tweaks to use the new platform properly, such as moving to a managed database or object storage instead of a hand-rolled one.
Neither improves your code, and that is the point. You buy supported infrastructure, security patches, and easier scaling for a fraction of a rewrite, and you do it without touching business logic that already works. It is often the right first step before a deeper refactor, because it stops the bleeding fast.
Reach for replatform or rehost when: the application logic is healthy but the runtime, OS, or hosting is unsupported, insecure, or about to be switched off.
Rewrite from scratch: the tempting trap
A full rewrite feels clean: throw away the mess, start fresh, do it right this time. It is also, in Joel Spolsky’s words, the single worst strategic mistake a software company can make. Netscape rewrote its browser instead of fixing it, went roughly three years between major releases, shipped no version 5 at all, and handed the market to Internet Explorer while the new code was still being written.
The reason is not that new code is bad. It is that the ugly old code encodes years of hard-won fixes: the weird tax rule, the browser quirk, the customer who sends malformed data every Friday. Rewrite from a blank page and you rediscover every one of those bugs the expensive way, in production, while your roadmap sits frozen and competitors keep shipping. The rewrite that ships in “three months” is usually the one that reaches feature parity in eighteen.
Reach for a full rewrite when: the platform is genuinely dead (unsupported language, no path forward), the domain has changed so much the old model no longer fits, and you have a clear spec plus the runway to reach parity. Even then, prefer the Strangler Fig below.
Replace: buy or adopt instead of building
If a system does something generic — email, CRM, a standard admin panel, off-the-shelf auth — the cheapest modernization is often to stop owning it. Replace retires the custom code and moves the job to a product or service that already solves it, and maintains it for you.
The catch is your differentiator. Replace the commodity parts, never the code that is the reason customers pay you. A DJ platform can buy authentication off the shelf; it cannot outsource its music-recognition engine. The skill is drawing that line honestly, and a good audit draws it for you before you sign anything.
Reach for replace when: the system does something commodity that a mature product already does better and cheaper, and it is not the thing that differentiates your business.
Strangler Fig: modernize a live product without a freeze
The Strangler Fig pattern is how you get most of the upside of a rewrite without the freeze. Named by Martin Fowler after the fig that grows around a tree until it replaces it, and documented in AWS’ own guidance, it works like this: put a router in front of the old system, then rebuild one slice of behaviour at a time, and point the router at the new code once each slice is proven. The old system keeps serving everything you have not migrated yet.

Figure 3. Traffic moves from the legacy monolith to new services one slice at a time, with no big-bang cutover.
Why it beats a big-bang rewrite: you ship value in weeks instead of at the end, every slice is small enough to reason about and roll back, and if you run out of budget halfway you still have a partly modernized system that works, not a half-written one that does not. It is more coordination than a rewrite, and the router is real work, but for any product with live users it is almost always the safer bet. The hard part is drawing the slice boundaries; an independent software architecture review maps those seams and tells you what to keep before the first slice moves.
Reach for the Strangler Fig when: you need to replace big chunks of an old system but cannot take it offline, and you want to keep shipping features while you modernize.
Weighing refactor vs rewrite on a live product?
We have run the Strangler Fig on production systems with real users. Let us map a slice-by-slice plan for yours in 30 minutes.
Refactor vs rewrite vs replatform vs replace
Choose phased modernization over a full rewrite whenever the old system has live users, earns revenue, or holds business rules nobody has written down; a phased path ships value in weeks and can stop halfway without leaving you with nothing. Choose a full rewrite only when the platform has no upgrade path, the spec is clear, and you can fund the months it takes to reach feature parity.
The same five questions decide every one of these: how much effort, how much downtime risk, does it keep your domain logic, when does it fit, and what bites you. Here they are side by side.
| Approach | Effort | Downtime risk | Keeps domain logic | Best when |
|---|---|---|---|---|
| Refactor | Low–medium | Low | Yes, fully | Good system, tangled code, supported stack |
| Replatform / rehost | Low | Low–medium | Yes, unchanged | Healthy code, dead or costly infrastructure |
| Strangler Fig rewrite | Medium–high | Low (incremental) | Rebuilt slice by slice | Big change needed, users cannot be frozen |
| Big-bang rewrite | High | High | Re-derived (risky) | Platform truly dead, clear spec, real runway |
| Replace | Low–medium | Medium (migration) | No, you drop it | Commodity job a product already does |
Read the table top to bottom and the pattern is clear: risk and effort climb as you move from fixing the code you have toward replacing it wholesale. Start as high in the list as your situation allows.
What legacy modernization costs: a worked example
Effort, not price, is the honest unit, because a day of engineering costs wildly different amounts depending on where and how you buy it. So price the work in engineer-weeks first, then multiply by your own blended rate. Figure 4 sizes the four paths for the same mid-size app.

Figure 4. Effort ranges for one mid-size app. The big-bang rewrite is roughly double the Strangler Fig for a worse risk profile.
Work a real example. Say you pick the Strangler Fig for a six-year-old SaaS with no test suite: Figure 4 puts that at 16–40 engineer-weeks. At a two-person team and a conservative blended $60 per hour, the low end is 16 × 40 = 640 hours, about $38,000; the high end is 40 × 40 = 1,600 hours, about $96,000. A big-bang rewrite of the same app (30–58 weeks) lands near $72,000–$139,000 and freezes your roadmap the whole time.
Two adjustments make those numbers real. Add a code audit up front (one to two weeks) so you are estimating from evidence, not vibes. And subtract for tooling: our Agent Engineering approach typically trims 25–40% off the build hours by putting AI on the mechanical parts, which we cost conservatively rather than promising the best case. If a vendor quotes you a fixed rewrite price without an audit, that is a red flag, not a bargain.
How AI changes legacy modernization in 2026
AI has made the mechanical parts of modernization dramatically cheaper, which changes the math but not the strategy. The 2026 toolset is real and shipping. Amazon Q Developer upgrades Java 8, 11 and 17 codebases to Java 17 or 21 with step-by-step diffs, and its sister service AWS Transform documents undocumented COBOL, decomposes mainframe monoliths and, since a December 2025 update, runs custom transformations on any code or framework, with AWS claiming up to 5x faster full-stack Windows modernization. IBM watsonx Code Assistant for Z translates mainframe COBOL toward Java. GitHub Copilot app modernization, generally available since September 2025, assesses Java and .NET apps, upgrades frameworks and dependencies, patches the build and containerizes the result.
| Tool | What it automates | Status, October 2026 |
|---|---|---|
| Amazon Q Developer | Java 8 / 11 / 17 upgrades to Java 17 or 21, dependency updates | Generally available |
| AWS Transform | Mainframe COBOL analysis and decomposition, .NET and VMware migration, custom code transformations | Custom capability added December 2025 |
| GitHub Copilot app modernization | Java and .NET assessment, framework upgrades, build fixes, containerization | Generally available since September 2025 |
| IBM watsonx Code Assistant for Z | COBOL understanding and COBOL-to-Java on IBM Z | Generally available |
What AI is genuinely good at: writing the missing tests that make old code safe to touch, generating documentation for systems whose authors left, doing framework and library upgrades, and drafting the first pass of a service extraction. That is exactly the grunt work that used to make modernization slow and expensive.
What it is not good at, and this matters: deciding whether to refactor or rewrite, understanding why a weird rule exists before deleting it, or shipping unreviewed. AI-generated migration code still needs a human, a test suite, and a review, or you have simply traded old debt for new debt faster. Used well it is a force multiplier on the strategy in this guide, not a replacement for it. If AI is part of your plan, our AI integration team wires it into the existing codebase safely.
A decision framework in five questions
Answer these top to bottom. The first “no” usually points straight at your move, and Figure 5 turns the same logic into a map you can hand to your team.

Figure 5. The five questions as a decision tree; walk the trunk and branch off at the first “no.”
1. Is the system still delivering business value? If no, retire it. Do not spend a cent modernizing something you are about to switch off.
2. Is the platform, runtime, and stack still supported? If no, replatform or rehost first, before you invest in the code that sits on top.
3. Is the domain logic worth keeping? If no — the system does a commodity job — replace it with a product built for that.
4. Can you change it safely today, with tests and reasonably modular code? If yes, refactor in place; you already have the foundation.
5. Do live users make a code freeze impossible? If yes, use the Strangler Fig. Only if you can freeze, have a clear spec, and have real runway does a full rebuild earn a place. When in doubt, book a second opinion before you commit the budget.
Mini-case: modernizing a 720,000-track platform
The situation. Franchise Record Pool runs a Shazam-style music-recognition platform for professional DJs, with a catalogue of more than 720,000 licensed tracks from Sony Music, Universal, Virgin and others, and working DJs (including Funkmaster Flex) depending on it daily. The product could not go dark for a modernization, and the rights-holders would not tolerate downtime on their catalogue.
The plan. Rather than a rewrite, we modernized around the live product, replacing pieces behind the running system so DJs kept working the whole time. Each slice shipped and proved itself before the next one started, which is the Strangler Fig discipline applied to a real catalogue business. The full build is written up in our FRP case study.
The outcome. A modern recognition and catalogue platform that still serves professional DJs and satisfies major-label licensing, delivered without the freeze a big-bang rewrite would have forced. Want a similar read on your own system? Book a 30-minute assessment and we will tell you which of the seven options actually fits.
Want a modernization plan with real numbers?
We start with a code audit and hand you a costed, module-by-module plan — refactor, strangle, or replace — before any build begins.
Five mistakes that sink modernization projects
1. Rewriting before auditing. Teams decide “rewrite” on a gut feeling about how bad the code is, then discover mid-build which parts were load-bearing. Audit first, so the strategy comes from evidence.
2. Modernizing with no tests. Changing legacy code without a safety net means every fix risks a new bug you will not catch until a customer does. Write the characterization tests first; that is what makes the code safe to touch.
3. The big-bang cutover. Flipping from old to new in one weekend concentrates every risk into one night. Migrate incrementally so each step is small and reversible.
4. Modernizing the commodity, not the differentiator. Spending your best engineers rebuilding auth or email while the core product stagnates is effort in the wrong place. Replace the generic, invest in the unique.
5. Treating data migration as an afterthought. Old systems hold years of messy, precious data, and moving it cleanly is often harder than the code. Plan the data path on day one, not the week before launch.
KPIs: how to tell modernization is working
Delivery KPIs. Track change lead time (commit to production) and deployment frequency, two of the four DORA delivery metrics. Modernization is working when a routine feature that used to take three weeks ships in three days, and deploys go from monthly and scary to daily and boring.
Quality and reliability KPIs. Track change-failure rate and mean time to recovery. Watch test coverage on the modules you have touched climb from zero toward a level where a green build actually means something. Incidents per month should trend down, not up.
Business KPIs. Track the share of engineering time spent on maintenance versus new work; a healthy shift is from the majority going to keeping-the-lights-on toward the majority going to new value. Add hosting cost per active user and time-to-onboard a new engineer, both of which should fall as the code gets clearer.
When not to modernize legacy code
Sometimes the right move is to do nothing, and a firm that only sells modernization will not tell you that. If a system is stable, cheap to run, rarely changes, and is not a security risk, leave it alone. “Old” is not a reason to spend money; boring-and-working is a feature, not a bug.
Hold off, too, when you cannot articulate the business outcome. “The code is ugly” is not a goal; “we need to add SSO and the auth module blocks it” is. Modernize the part that stands between you and a real objective, and only that part. If the whole system is due to be sunset next year, do not modernize it at all — ride it out.
The exception is security. An unsupported runtime with known, unpatched vulnerabilities is not “boring and working,” it is a breach waiting to happen, and that alone can justify a replatform even when nothing else would.
FAQ
What is legacy code modernization?
Legacy code modernization (legacy system modernization, at product scale) is updating old software — its code, platform, or architecture — so it costs less to run, carries less risk, and can support new features again. It spans a spectrum from a light refactor of code you keep to retiring the system and replacing it with a new product.
Should I refactor or rewrite legacy code?
Refactor if the system still fits the business and runs on a supported stack; you keep all the hard-won logic and ship faster. Rewrite only if the platform is truly dead or the domain has changed fundamentally, and even then prefer an incremental Strangler Fig rewrite over a big-bang one.
How much does legacy system modernization cost?
Price it in engineer-weeks, then multiply by your blended rate. For a mid-size app, a refactor runs roughly 6–14 weeks, a Strangler Fig rewrite 16–40, and a big-bang rewrite 30–58. At a $60/hour blended rate, the Strangler Fig path is about $38,000 to $96,000. A code audit first prices your specific system properly.
What is the Strangler Fig pattern?
Named by Martin Fowler, the Strangler Fig pattern replaces a legacy system incrementally: you put a router in front of it, rebuild one slice of behaviour at a time, and redirect traffic to the new code as each slice is proven. The old system serves users the whole way, so there is no big-bang cutover and no freeze.
How long does legacy modernization take?
A focused code audit takes one to two weeks. After that it depends on the path: a refactor of a mid-size app is often 6–14 engineer-weeks, while an incremental Strangler Fig rewrite is 16–40. The Strangler Fig ships value continuously, so you see results in weeks rather than waiting for a single end date.
Can AI modernize legacy code automatically?
AI accelerates the mechanical parts — writing missing tests, generating docs, upgrading frameworks, and drafting service extractions with tools like Amazon Q Developer and IBM watsonx Code Assistant for Z. It does not decide strategy or ship unreviewed. AI-generated migration code still needs a test suite and human review, or you trade old debt for new debt faster.
What are the biggest risks in legacy modernization?
The classic ones are rewriting before auditing, changing code with no tests, a big-bang cutover that concentrates all risk into one night, spending effort on commodity features instead of your differentiator, and treating data migration as an afterthought. Incremental delivery and a code audit up front defuse most of them.
When is a full rewrite the right call?
When the platform is genuinely dead with no upgrade path, the domain has changed so much the old model no longer fits, and you have both a clear spec and the runway to reach feature parity. Even in that case, an incremental Strangler Fig rewrite is usually safer than freezing the roadmap for a big-bang rewrite.
Can I modernize a legacy system without rewriting the source code?
Yes. Encapsulating it behind an API, rehosting or replatforming it, refactoring it in place behind tests, or replacing one commodity module at a time all keep the existing code. Only a platform with no upgrade path really needs a rewrite, and even then the Strangler Fig rebuilds it slice by slice.
How do I choose between a phased modernization and a full rewrite?
Choose phased modernization when the system has live users, earns revenue, or holds undocumented business rules, because it ships value in weeks and can stop halfway safely. Choose a full rewrite only when the platform is dead, the spec is clear, and you can fund the long road to feature parity.
How do you refactor legacy code safely?
Pin down current behaviour with characterization tests, break dependencies so the code can run under test, then refactor in small commits that never mix cleanup with new features. Refactor only around the code the next business change touches, and ship daily behind feature flags for risky parts.
Which runtimes reached end of support in 2026?
.NET 8 and .NET 9 lose support on November 10, 2026, Node.js 20 reached end of life on April 30, 2026, Python 3.10 on October 1, 2026, and paid security updates for Windows Server 2012 and 2012 R2 ended on October 13, 2026. Products on these runtimes no longer get security patches.
What to read next
Development
Code Refactoring in Plain Words
The how-to behind the refactor option: when, why, and how to pay down tech debt.
Development
What Is a Code Audit and How to Run One
The step you take before modernizing: process, tools, and pricing for 2026.
Development
Software Code Audit Checklist
A 12-section checklist founders can use to grade a codebase before investing.
Case study
Modernizing a 720K-Track DJ Platform
How we rebuilt a live music-recognition platform without taking it offline.
Processes
Why Time Estimates Miss (and How to Read a Quote)
How to read a modernization quote and spot the padding before you sign.
Ready to modernize without the gamble?
Legacy is a cost problem, not an age problem, and you have seven ways to fix it, not two. Start as far left on the spectrum as your situation allows: encapsulate or replatform to stop the bleeding, refactor the code that still fits, replace the commodity parts, and reserve the rewrite for a platform that is truly dead. When you do need a big change on a live product, the Strangler Fig gives you the upside without the freeze.
The one move that de-risks all of it is starting with a code audit instead of a rewrite, so your strategy comes from evidence. That is where we begin with every client, and we will tell you honestly if the answer is to leave your code alone.


The handbook · 7 volumes
Fora Soft Video Engineering Handbook
Many legacy systems we modernize are media products, like the 720,000-track platform in this guide. Our seven-volume handbook covers the stack such systems run on; start with Volume 3 for players, CDNs and delivery, then Volume 4 for audio codecs and loudness and Volume 1 for encoding, before deciding which modules to refactor. Written by Nikolay Sapunov, CEO at Fora Soft.
Browse the handbook on Amazon →7 volumes · 9,000+ pages · Kindle & paperback
Turn old code into a competitive advantage?
Fora Soft has modernized live products since 2005. Book a 30-minute call and start with a free-standing audit and a costed plan — refactor, strangle, or replace.