Blog post

Modernizing legacy codebases

Vivek Singh

-
August 11, 2025
Engineering Practices
Legacy Modernization
Software Architecture
Tech Debt

The problems of legacy software continues to grow in their magnitude. But generative AI has opened up new possibilities for modernisation of such systems. The cost and feasibility distance between legacy software code and a modernised version of it has certainly gotten smaller in the imagination of its stakeholders. It is likely that lot of legacy software systems will be modernised in the coming years. Hence, it makes sense to better understand how to approach these projects and work on them.

Some examples of such projects are:

  • programming language change (e.g. from active server pages to C#/.NET)
  • significant version upgrade (e.g. from Java 7/8 to Java 17/21)
  • major core library upgrade (e.g. from Struts to Spring MVC)
  • database change (e.g. from SqlServer to PostgreSQL)
  • architecture style change (e.g. from monolithic to micro-services, single module to multi-module)

The core idea of modernisation is that the main functional part of the code can be preserved while migrating. Lets first call out what is the functional part of the source code, and what is not. This is contextual - but quite likely the cross functional concerns like - serialization, hydration, configuration management, logging, http interceptors/filters, can be considered to be cross functional and the rest as functional. Cross functional code usually forms a small percentage of the codebase. The migration project may do the following with them.

  • Functional code: Very-minimal change or change done via a dependable automated process
  • Cross functional code: take help of automation and AI - but with an acceptance that one may need to change code by hand as well.
A modernisation project where the functional part of code has to be modified extensively by hand, is an extremely risky proposition.

Role of AI

Use of AI has been successful in making even previous considered unthinkable migrations possible, like migrating code into a different language (one of our teams did a successful migration from asp to C#, without knowing much of C#). This type of batch migration requires right AI tools. The main characteristics of these tools being:

  • ability to change dozens of files at a time without stopping and waiting for user confirmation
  • being able to perform such changes with a reasonable performance, i.e. without putting the developer to sleep.

It is early days but I have found that Amazon Q, Windsurf can achieve this to some extent when provided with detailed prompts.

It is important that the engineers have flexibility in choosing the AI tools and even use multiple AI tools in the same category since they may have different strengths that are usable in different contexts during a migration project.

Even with AI performing modular migration, if possible, is a good idea. I recently spent some time playing spiking the idea to migrate a project from Java 7 to Java 21, moving from Struts/JSP to Spring MVC+React. I concluded that doing this in two steps may make more sense - first migrate Java+Struts to Java+Spring MVC and then from JSP to React. The first migration going to production before starting the next one.

A puzzle that all engineers face which is how to best utilize one's time when AI is generating code. This problem gets multiplied when in migration projects since the batch AI can create even longer wait times.

Lastly, there are other aspects of legacy migration projects that become doable and interesting due to AI. It can help in understanding the code and developing useful before and after test cases.

Getting feedback in migration work

It is important to identify small milestones in migration projects. It could be something like the following for a web service project:

  • one module source successful compile
  • one module test compile successful
  • all modules source compile successful
  • successfully run the application (without expecting it serve any request)
  • call one GET endpoint
  • call one POST endpoint
  • run a unit test
  • run an integration test
  • run all unit tests
  • run all integration tests

These are just indicative and will vary based on your project. It is important to not assign percentage completion to these milestones - unless one is super confident. Legacy modernisation are not standardized efforts with historical data to draw upon.

One important aspect to callout here is that to get complete end to end feedback like a story card in quick time, is elusive. Hence the smallest unit of work that can be put into production is quite large. This lies at the heart of the complexity of migration, or else it would not need to be treated as a different type of work. This is the key psychological shift required for a modern agile software engineer.

How to enjoy migration projects?

Lets be honest, migration projects are not super enjoyable - compared to regular software projects. This is primarily because the feedback loops are long.

The most important factor is to change one's perspective on what is the production system. In legacy modernisation projects, source code in-itself becomes the production system.

On such projects it helps shift one's gaze away the real production system, for some time. This shift allows for finding fulfillment from the feedback of the smaller milestones (even though they are no production complete).

Along with that one can also look at the opportunities presented by such projects:

  • Learn about various AI tools, ecosystem, their applicability and how to use them.
  • Migration strategy and process, is your software architecture - hence reasoning, iterating, and improving on it is the craft.
  • It is an opportunity to learn about the internals of the cross functional areas - since they require far more attention than usual.
  • They may be opportunities to improve on regex, shell scripting to automate some processes.
  • There are usually opportunities to improve on the build and deployment scripts.

Overall, if the team is provided with the right tools and engineers can approach such projects differently than regular software development projects - then not only the process can be more enjoyable but also the results can be better.

Related Blog Posts