Skip to main content
Golux Group
Insights

Software engineering · Consideration

Legacy Software Modernization: The Complete Guide

Rewrite, replatform, refactor or encapsulate? An assessment method, the strangler-fig pattern in practice, and how to keep the business running throughout.

Golux Group Engineering · · 13 min read

The decision to modernise a legacy software system is rarely simple. These systems often represent decades of accumulated business logic, running core operations reliably, if inflexibly. The impulse to leave them untouched is understandable. Yet, the cost of inaction is a slow, compounding tax on agility, security, and talent retention. The question is not if you will be forced to modernise, but on what terms—proactively and strategically, or reactively in a crisis.

At Golux Group, we have guided numerous organisations through this complex journey. The most successful modernisations are not "big bang" rewrites but carefully sequenced programmes of work that manage risk, deliver incremental value, and treat the legacy system with the respect it deserves, even while systematically dismantling it. This guide outlines the strategic framework we use, from initial assessment to phased migration, to help leaders make sound decisions and de-risk one of the most significant undertakings in the IT lifecycle.

The real cost of not modernising

The visible cost of a legacy system is its direct maintenance budget. The invisible costs, however, are far greater and more corrosive to the business. In our engagements, we frequently find that over 70% of a technology budget is consumed by simply "keeping the lights on," leaving little room for innovation. This cost manifests in several critical areas.

Opportunity Cost: This is the most significant hidden expense. Your legacy system's architecture dictates what your business can and cannot do.

  • Slow Time-to-Market: Need to launch a new product, enter a new market, or change a pricing model? If a change that should take weeks takes nine months and requires a team of specialists, you are ceding ground to more agile competitors.
  • Integration Barriers: The modern business ecosystem is built on APIs. Your inability to easily integrate with partners, suppliers, or new SaaS tools isolates your business. A European insurer we worked with was unable to partner with new digital-first brokers because its mainframe policy system couldn't offer real-time quoting APIs.
  • Data Inaccessibility: Data is locked in arcane databases and proprietary formats, making modern business intelligence, analytics, and AI/ML initiatives impossible. The data exists, but it cannot be leveraged for competitive advantage.

Talent and Morale Cost: The technology you run directly impacts the talent you can attract and retain.

  • Hiring Difficulty: Few top-tier engineers are looking to build a career in COBOL, ColdFusion, or decade-old versions of Java or .NET. The talent pool is shrinking and becoming prohibitively expensive.
  • Team Attrition: Your best engineers want to solve interesting problems with modern tools. Forcing them to work exclusively on brittle, poorly-documented legacy code is a primary cause of developer churn. The knowledge of the system walks out the door with them.

Risk and Security Cost: Ageing systems are a magnet for unacceptable risk.

  • Security Vulnerabilities: Unsupported operating systems, libraries, and frameworks are no longer receiving security patches. Each unpatched CVE is an open invitation for a breach.
  • Operational Fragility: These systems often lack modern observability—no detailed logging, tracing, or metrics. When something goes wrong, it's an "all hands on deck" crisis to find the root cause, leading to extended and damaging outages.
  • Compliance Failure: Regulations like GDPR require capabilities such as data portability ("right to access") and erasure ("right to be forgotten"). Bolting these onto a monolithic legacy system is often architecturally infeasible or requires herculean effort, exposing the firm to significant fines.

Assessment: business value, risk, and change cost

Before writing a single line of new code, a successful modernisation begins with a clear-eyed assessment of the application portfolio. Not all legacy systems are created equal. Some can be tolerated, some must be retired, and some are prime candidates for immediate modernisation. We triage systems using a simple but effective three-factor model: Business Value, Technical Condition, and Cost of Change.

  1. Business Value: How critical is this system to the company's mission? Does it generate revenue, manage core operations, or provide a key competitive differentiator? A system with low business value, no matter how technically obsolete, is not a priority for a costly modernisation.
  2. Technical Condition: How sound is the application's architecture, codebase, and underlying infrastructure? We assess factors like code complexity (cyclomatic complexity), test coverage, the availability of documentation, and dependencies on unsupported platforms.
  3. Cost of Change: This is a proxy for technical debt. We ask: "What is the estimated effort to add a significant new feature?" A high cost of change indicates a brittle, tightly-coupled system where any modification has unpredictable ripple effects.

Plotting your applications against these criteria helps prioritise your efforts.

Sample Application Portfolio Assessment

ApplicationPrimary FunctionBusiness ValueTechnical ConditionCost of ChangeRecommended Action
MonolithCoreCore Order ProcessingHighPoor (VB6, SQL Server 2008)Very HighModernise (High Priority)
ReportingEngineBatch end-of-day reportsMediumFair (Java 8 monolith)MediumRefactor/Replatform
LegacyCRMOld customer contactsLowVery Poor (Access DB)HighRetire & Migrate Data
WarehouseAPIInternal warehouse opsHighGood (Modern .NET)LowMaintain

This triage process moves the conversation from "everything is a mess" to a strategic, risk-adjusted roadmap. The focus immediately shifts to MonolithCore, the system that is both critical to the business and a major drag on progress.

The five Rs and how to choose between them

Once you have prioritised which systems to address, you must choose the right strategy. The "5 Rs" (popularised by Gartner) provide a useful vocabulary for your options. The key is to select the strategy that best matches the system's context and your business goals, not to apply a one-size-fits-all approach.

Comparison of Modernisation Strategies

StrategyDescriptionTypical CostRiskTime to ValueBest For
Rehost"Lift and Shift". Move the application as-is to a modern infrastructure (IaaS).LowLowFastApplications you can't modify but want to get out of your own data centre.
Replatform"Lift and Tinker". Make small optimisations to run on a cloud platform (e.g., containerise).Low-MediumLowFastSound applications that can benefit from cloud-native features (e.g., auto-scaling) with minimal code changes.
RefactorRestructure existing code to improve its design without changing its external behaviour.Medium-HighMediumMediumValuable, complex systems where the core business logic is sound but the architecture is holding it back.
Replace"Rip and Replace". Decommission the old system and build a new one from scratch.Very HighVery HighSlowSystems where the business requirements have fundamentally changed, or the underlying technology is completely unsupportable.
RetireDecommission the application and its functions entirely.Very LowLowImmediateRedundant or low-value applications where functionality is no longer needed or is provided elsewhere.

In our experience, a full Replace (or rewrite) is the riskiest path and should be avoided for complex core systems. It creates a long tunnel of development with no value delivered until the end, and it is famously prone to the "second-system effect," where scope expands uncontrollably.

The most pragmatic and powerful approach for complex systems is a combination of Refactor and Replace applied incrementally, using a pattern known as the Strangler-Fig.

Strangler-fig migration in practice

The Strangler-Fig pattern, named by Martin Fowler, is the cornerstone of modern, low-risk legacy migration. The metaphor is apt: a new application (the "fig") grows over and around an old one (the "host tree"), gradually starving it of resources and traffic until the old system can be safely decommissioned.

This approach avoids a high-risk, multi-year rewrite. Instead, it delivers value incrementally, manages risk at each step, and allows the business to continue operating without interruption. The process hinges on a component called the Strangler Facade.

                 +---------------------+
                 |   User / API Call   |
                 +---------------------+
                           |
                           v
+-------------------------------------------------------------+
|                  Strangler Facade                           |
|      (API Gateway, Reverse Proxy, or Custom Router)         |
|                                                             |
|   IF request is for /new-feature-A  ->  Route to New Service|
|   IF request is for /old-feature-B  ->  Route to Legacy App |
|                                                             |
+-------------------------------------------------------------+
         |                                      |
         v                                      v
+---------------------+                +----------------------+
|    New Service A    |                |                      |
| (Microservice, etc.)|                |   Legacy Monolith    |
|   (Modern Stack)    |                |                      |
+---------------------+                +----------------------+

The migration proceeds in a disciplined sequence:

  1. Introduce the Facade: All traffic to the legacy system is first routed through the Strangler Facade. Initially, it does nothing but pass 100% of traffic to the legacy application. This is a critical first step that gives you a control point. This facade can be an API Gateway (like Kong or AWS API Gateway) or a configured web server (like Nginx).
  2. Identify a "Seam": Find a logical, bounded piece of functionality to carve out. This might be a single API endpoint, a user profile page, or a specific business workflow like "generate invoice." Using principles from Domain-Driven Design to identify these "bounded contexts" is highly effective.
  3. Build the New Component: Develop the replacement functionality as a new, independent service using a modern stack. This is a standard software engineering task, but it must be built with a clean separation from the legacy world.
  4. Divert Traffic: Configure the Strangler Facade to route traffic for the newly implemented functionality to the new service. All other traffic continues to flow to the legacy system.
  5. Monitor and Verify: Closely monitor the new component for errors, performance, and business correctness. At this stage, you might run the systems in parallel (more on this later).
  6. Repeat: Continue this process, incrementally "strangling" pieces of the legacy application, moving them to new services. Over time, the legacy monolith shrinks in scope and importance until it can be turned off.

This strategy transforms a monolithic, high-stakes project into a manageable series of smaller, de-risked steps. You can review our case studies to see how this incremental approach has been applied to complex client systems.

Data migration, reconciliation and cutover

While the Strangler-Fig pattern handles application logic, data is often the most challenging part of any modernisation. Business data is the asset; applications are just the tools that manipulate it. A flawed data migration can lead to financial loss, regulatory breaches, and a catastrophic loss of customer trust.

A "big bang" data migration—where you shut the system down, move all the data overnight, and turn the new one on—is rarely feasible for critical systems. The risk of extended downtime and data corruption is too high. A phased approach is superior.

Data Synchronisation during Transition: During a long migration, both the legacy system and new services need to coexist and potentially operate on the same data. The key is to establish a reliable data synchronisation mechanism.

  • Change Data Capture (CDC): This is a powerful technique. Tools like Debezium can monitor the legacy database's transaction log and stream any changes (inserts, updates, deletes) to a message broker like Kafka. New services can then consume these events to keep their own databases up-to-date in near real-time. This is a core competency of our data engineering team.
  • Data Virtualisation / Anti-Corruption Layer: When a new service needs data that still resides in the legacy system, it should not query the legacy database directly. This creates tight coupling. Instead, it should go through an "Anti-Corruption Layer"—an API that translates the old data model into the clean, new domain model. This protects the integrity of the new system's design.

Reconciliation: You must be able to prove that the migration was successful. This requires a rigorous reconciliation process.

  • Technical Reconciliation: This involves comparing record counts, checksums of data rows, and other technical measures to ensure no data was lost or garbled.
  • Business Reconciliation: This is even more important. It involves running business-level checks. For example, "Does the sum of all invoices for Q3 in the new system match the sum in the old system to the cent?" or "Is the number of active customer policies identical between the two systems?" These checks provide the ultimate confidence to business stakeholders.

Keeping the business running: parallel runs and rollback

A core principle of any professional migration is to never compromise ongoing business operations. This requires building safety mechanisms into the migration process itself. Two key techniques are parallel runs and robust rollback strategies.

Parallel Runs: For critical business logic—such as pricing calculations, risk analysis, or logistics routing—you cannot simply trust that the new code is correct. A parallel run is the ultimate validation.

  1. The Strangler Facade is configured to send incoming requests to both the legacy system and the new service simultaneously (this is often called "dark launching" or "shadowing").
  2. The legacy system's response is returned to the user as normal.
  3. The new service's response is not sent to the user but is instead logged and compared against the legacy response.
  4. Automated systems flag any discrepancies. This allows you to find and fix subtle bugs in the new implementation (e.g., floating-point rounding differences, divergent business rule interpretations) with zero impact on live customers.

Feature Flags and Rollback: The ability to instantly revert to the old system is your most important safety net. This is not an afterthought; it must be designed in from the beginning.

  • Feature Flags: The decision in the Strangler Facade to route to a new service should be controlled by a feature flag system (like LaunchDarkly or an in-house equivalent). This allows you to turn the new functionality on for a small percentage of users (e.g., 1%, 5%, 50%) and monitor its performance.
  • The "Kill Switch": If the new service exhibits critical failures, you can flip the feature flag and instantly redirect 100% of traffic back to the stable legacy system. This "kill switch" can reduce a potentially hours-long outage to a few seconds of degraded service. This level of operational discipline is fundamental to how we work.

Cost ranges and typical timelines

Legacy modernisation is a significant investment, not a short-term project. Costs and timelines vary dramatically based on the complexity, size, and criticality of the system. Providing a generic price is impossible, but we can share realistic ranges based on our experience. For a deeper dive into cost structures, our guide on how much custom software development costs is a useful resource.

All estimates below assume 2026 European senior engineering blended rates of approximately €1,100-€1,300 per person-day.

Worked Example 1: Mid-Market Logistics Platform

  • Client: A Series A European logistics platform.
  • Legacy System: A monolithic Ruby on Rails application from the early 2010s, struggling to handle real-time tracking demands and partner integrations.
  • Goal: Move to a modern, event-driven architecture using a cloud-native stack (e.g., Kotlin/Java services on Kubernetes) to improve scalability and enable new product offerings.
  • Approach: Strangler-Fig migration, focusing on carving out the tracking and routing domains first.
  • Team: 1 technical lead, 4 senior engineers, 1 DevOps specialist.
  • Timeline: 18-24 months for ~80% of functionality to be migrated.
  • Estimated Cost: A team of 6 for 21 months at an average of 20 workdays per month and a blended day rate of €1,200 is approximately €3.0M. This covers the core migration team; product management and other roles are additional.

Worked Example 2: Enterprise Insurer's Core System

  • Client: A large European insurer.
  • Legacy System: A 30-year-old mainframe (COBOL/DB2) system for policy administration. It is stable but extremely expensive to run and almost impossible to change.
  • Goal: Replace the mainframe to reduce exorbitant licensing and hardware costs and dramatically shorten the time-to-market for new insurance products.
  • Approach: A multi-year programme combining the Strangler-Fig pattern for user-facing interactions and a robust CDC-based data synchronisation approach for the back-end data.
  • Team: A programme of multiple teams (pods), starting with a core team of ~15 people (architects, leads, engineers) and potentially scaling up.
  • Timeline: 3-5 years. This is a strategic business transformation, not just an IT project.
  • Estimated Cost: The initial 3-year budget for a core team of 15 would be in the range of €10M - €13M. The total programme cost over five years, including scaling teams and infrastructure, could easily exceed €25M. The business case is justified by retiring annual mainframe costs that run into the millions.

Modernisation as an enabler for AI

For many C-level leaders, modernisation can feel like a defensive, cost-focused activity. However, its most compelling benefit is offensive: it unlocks the future. Specifically, you cannot have a serious AI strategy with a legacy architecture.

Legacy systems are AI-blockers:

  • Data is Siloed: Data is trapped in formats and databases that are inaccessible to modern data platforms and ML frameworks.
  • No Real-Time Capability: Batch-oriented architectures cannot support the real-time data streams required for dynamic pricing, fraud detection, or recommendation engines.
  • No APIs: Modern AI models (especially large language models) are consumed and integrated via APIs. If your core systems cannot communicate via APIs, they cannot leverage these transformative technologies.

A modernised architecture, built on principles of modularity, APIs, and accessible data, is the foundation for AI. You can see this clearly in our work on modern software architecture.

  • A retailer that modernises its e-commerce platform can finally build a real-time recommendation engine.
  • An insurer that moves its claims system to a modern platform can use an LLM to summarise adjustor notes, but only because the notes are now accessible via a secure, internal API.
  • A logistics company that modernises its routing engine can feed real-time traffic and weather data into an ML model to optimise delivery routes dynamically.

Modernisation is not just about paying down technical debt. It is the necessary preparatory work for building a smarter, more data-driven, and ultimately more competitive organisation.

Frequently asked questions

Should we rewrite or refactor a legacy system?

By default, you should refactor and modernise incrementally using a pattern like Strangler-Fig. A full rewrite is an extremely high-risk, "bet the company" endeavour that we counsel against for any non-trivial core system. The time to deliver value is too long, the risk of failure is high, and the business is starved of new features during the process. A complete rewrite should only be considered in two extreme cases: the underlying platform is entirely unsupportable (e.g., a mainframe with no available talent), or the company's business model has pivoted so radically that the original domain model no longer reflects reality at all.

Key takeaways

  • Modernisation is a business imperative, driven by the need for agility, security, and talent. The cost of inaction is a hidden tax on growth.
  • Begin with a strategic assessment of your application portfolio. Prioritise based on business value, technical condition, and the cost of change.
  • For complex systems, the Strangler-Fig pattern is the default, de-risked approach. It delivers value incrementally and keeps the business running.
  • Data migration is the most difficult and riskiest part of the process. Plan it meticulously with synchronisation, reconciliation, and anti-corruption layers.
  • Modernisation is a multi-year programme, not a short-term project. Budget for it as a strategic investment with realistic timelines and senior-level sponsorship.
  • The ultimate goal is to enable future innovation. A modern architecture is the prerequisite for leveraging advanced analytics and AI.

Successfully navigating a legacy modernisation is one of the most impactful initiatives a technology leader can undertake. It's a complex journey that requires a strategic partner with deep experience in both modern architectures and the pragmatics of enterprise migration. The first step is always a clear-eyed assessment of your current architecture and a realistic roadmap for the future.

How we help with this

Talk to engineers

Get a free AI architecture assessment

We review your data, model and delivery setup and send back a written architecture opinion.

Weekly digest

Engineering signal, zero noise.

A hand-picked list of the best AI and product engineering reads, plus build notes from real Golux projects.

One email a week. No spam, unsubscribe any time.

Golux Group

Join Golux Club
and get special offers from our team

Join