Articles
Revolutionizing Application Modernization with GenAI and AWS

One of the biggest challenges facing enterprises in the ever-evolving digital landscape is legacy software. Despite rapid technological advancements, a huge part of enterprise code still resides in legacy languages like COBOL, Fortran, and VB6. This legacy codebase carries a heavy burden: not only is it expensive to maintain, but it also hinders innovation, agility, and scalability.
Traditional approaches to modernization — manual rewrites or re-architectures — are time-consuming, costly, and risky. However, a new wave of transformation is sweeping through the IT world: Generative AI (GenAI)-enhanced modernization.
The Definition of Legacy
The biggest challenge is to define what exactly “legacy software” or “legacy code” means. During numerous discussions with my colleagues and customers, various attributes of legacy code were mentioned:
- Legacy means the code is written in an old language, outdated language version, or an old framework. Using this definition, COBOL, VB6, PHP 5, or .NET Windows Forms application is legacy.
- Legacy means that no one in the company understands the code. This definition is simple: once you feel a lack of expertise to maintain the application efficiently, it becomes legacy.
- Legacy means that the framework or technology behind the application code is no longer maintained. In this context, an outdated and unmaintained version of a particular framework means that the application is legacy.
- Legacy means that the overall user experience, scalability, availability, infrastructure, or general attractiveness of the application is not sufficient or does not exist.
- Patterns used in legacy software could have been good practices many years ago, but are no longer desired. For example, keeping the logic in the database using stored procedures was a good choice 25 years ago, but now it is considered a problem from a maintainability and testability perspective.
There are potentially many more factors defining the code as legacy, but even this short list proves that various aspects might decide here. For example, COBOL code might be considered legacy and non-legacy, depending on the criteria used.
The Pain Points of Legacy Systems
Modernization has long been an issue for organizations. Legacy systems introduce a lot of operational inefficiencies and business risks:
- Lack of skilled developers for outdated languages – you can’t maintain legacy software if you have no developers who can do that. For old, outdated technologies, nobody even wants to work with them.
- Exorbitant maintenance costs—this is related to the first point; if you can’t find people who want to maintain your legacy app, you probably have to pay more. But also, if your product is successful, you might have to scale it up, which is typically expensive for legacy software due to licensing costs or the inability to scale horizontally.
- Performance and scalability bottlenecks—Performance might be bad because of the internal software design. In old monolithic applications, scalability is often not an option, and improving performance metrics requires lots of money for devices, licenses, and software updates.
- Security vulnerabilities—if the software is old, it might also be based on unmaintained technologies. Of course, it doesn’t have to be an issue, but it typically is—not only because of the real risk but quite often because of compliance criteria.
- Technical debt accumulation—well, if the application is old, it was probably updated many times, and many new features were added. If you’re a software developer, you probably know how this process looks for legacy software: let’s add the new code in the new place to not destroy something that already works, but the new code is similar to the old one, thus increasing the technical debt.
As a result, companies lose significant time just managing technical debt instead of innovating. Legacy software, though mission-critical, becomes a bottleneck rather than a business enabler.
Traditional Modernization: Slow and Risky
Historically, modernization involved one of three primary strategies:
- Rip and Replace – Rebuild the application from scratch. Though it offers a fresh start, it risks knowledge loss, cost overruns, and downtime. To be honest, it’s sometimes the only possible strategy, for instance, when the legacy software is developed in the technology that you want to remove from your landscape.
- Lift and Shift – Move applications to a new infrastructure or platform without rewriting. Quick but retains inefficiencies and technical debt. Lift & Shift might also be related to a modernization process changing the technology in the simple rewriting process, which keeps the architecture and code structure but changes the tech stack. Typically, it may be a relatively simple way to modernize, but this process does not remove the technical debt – it is still there, just in a different technology.
- Manual Rewrite or Re-architecture – Labor-intensive, high-risk, and often requiring months or years of work. It’s close to rip & replace but is usually focused on maintaining the overall application stack (database technology, data layers, event bus, etc.) while re-architecting the application core.
Each of these approaches is limited by a fundamental constraint: human bandwidth. Analyzing millions of lines of code, understanding undocumented logic, and safely migrating functionality is a super difficult and risky task. What if we could automate it a little bit?
Enter GenAI: A Paradigm Shift in Modernization
GenAI — driven by powerful large language models (LLMs) — is transforming software modernization by introducing intelligent automation into every step of the journey. Rather than relying on human effort alone, GenAI augments developers by:
- Understanding codebases at scale—What if we could understand what legacy software is really about, how it works, where the critical components are in the code, etc.?
- Extracting non-existent documentation—Legacy applications usually lack any documentation. What if we could reverse engineer it?
- Generating code recommendations and templates—GenAI makes it relatively simple to generate modernization recommendations and boilerplate code. We can utilize this feature to speed up the boring work.
- Refactoring code semantically, not just syntactically, is related to the “re-architecture/manual rewrites” scenario above. This process is typically syntactic. We can use GenAI to migrate semantically instead.
- Reducing human errors and the infamous “blank page” problem—“the curse of the blank page”—might be easily avoided. Nobody likes to start from nothing, but GenAI can help start from something useful.
By automating the analysis, documentation, and transformation of legacy code, GenAI reduces project risk, accelerates delivery timelines, and allows human teams to focus on high-value decisions. Let’s enumerate these tasks explicitly:
Initial Investigation
One of GenAI's earliest wins is speeding up the initial code analysis. By automatically identifying frameworks, dependencies, and technologies in use, GenAI minimizes the time spent on discovery, allowing teams to kickstart planning quickly.
Documentation Recovery
Legacy applications often lack documentation. GenAI can generate high-quality documentation, from high-level architectural overviews to detailed module descriptions — enabling better understanding and smoother transitions.
Technical Debt Detection
GenAI can surface hidden technical debt by identifying poor code practices, security risks, and architectural bottlenecks, helping prioritize what to modernize first.
Strategic Recommendations
By analyzing legacy systems in the context of business needs, GenAI can propose modernization strategies aligned with objectives — such as cost reduction, scalability, or compliance.
Boilerplate Code Generation
Repetitive foundational code — such as API scaffolds, repositories, and service classes — can be auto-generated, saving developers from tedious tasks and improving consistency.
Automated Code Transformation
Whether migrating from a legacy database, monolith to microservices, or one framework to another, GenAI can intelligently refactor and translate large portions of code, preserving semantics. Of course, it’s almost never perfect and requires human intervention.
The New GenAI-Powered Modernization Workflow
We also need to change the typical SDLC when modernizing with GenAI. The process must include GenAI-supported parts and human validation. Here’s what the GenAI-enhanced workflow might look like:
- Code Inventory & Analysis GenAI can rapidly ingest and understand large legacy codebases, mapping dependencies, frameworks, and architectural patterns.
- LLM-Powered Transformation Large language models suggest architectural improvements, code refactors, and migration paths. Of course, LLMs can also migrate the code to another technology.
- Human-in-the-Loop Validation Developers review recommendations to ensure compliance, performance, and contextual accuracy.
- Test-Driven Verification Continuous testing ensures functional parity during and after modernization.
- Incremental Deployment Modernized components are integrated and deployed in stages to minimize disruption.
Modernization with AWS
For GenAI-enhanced modernization, we can use multiple tools, but let’s focus on AWS’s ones from a slightly specific perspective. On the one hand, we can utilize the power of off-the-shelf tools, like CursorAI, Copilot, RooCode, or Amazon Q. But the problem is that you can’t really control what they do behind the scenes (although they often do a great job!).
Typically, such tools have large system prompts with many guardrails and rules designed to help you work faster and more reliably. But as a result, you don’t know what they do. You can’t control their complex agentic flow. If they do what you want, that’s great! But for complex automation tasks, they are quite often insufficient.
That’s why it might be a good idea to utilize cloud services and automate the process in a custom way. What we do, in fact, is create the modernization workflow with AWS services, which could help us experiment and automate. Let me give an example to describe it in detail.
Modernizing a .NET Monolith with GenAI
Consider a 600,000-line ASP.NET Web Forms application managing orders, billing, and inventory with the following attributes:
- No microservices,
- No documentation,
- No tests,
- Tightly coupled logic.
How to start modernizing? Here you have the steps that we followed when migrating this code to .NET Core.
Code Ingestion & Analysis: GenAI helped us to parse Web Forms, business logic, and SQL code, generating dependency maps and identifying hotspots. We’ve done that without documentation, even though the image below presents it as an input. Documentation would certainly help!
We first used Amazon Bedrock models to investigate the code, gather interesting insights, and create documentation of the files and modules. Then, the documentation was stored in OpenSearch Serverless with the appropriate embeddings. This helps to navigate between various parts of the system when discovering relations, creating a more in-depth analysis of the workflows and internal dependencies. We have also partially used static analysis tools, but they were not crucial in that process.

Knowledge Extraction and Experimentation: At the end of the previous step, we obtained full comprehensive documentation, and we could also use the chatbot, which had complex knowledge about the system and its structure. And now the interesting part begins: we used that knowledge and the legacy code to experiment with modernization.
Typically, it looks as follows:
- Take the old code,
- Take the description,
- Prepare the pattern (how do you expect the new code to look?),
- Request for automatic migration.
And repeat if the results are not satisfying. Typically, the problem is in your prompt or in your automation steps. For example, if you want to generate the new files consistently, you probably need to put the already generated files into context, so that LLM knew what is the naming convention or what functions have already been implemented. There are a lot of experiments to do here!
Experimentation is usually performed in Jupyter Notebooks, and in our case, it was AWS SageMaker AI to enable team collaboration. After the experimentation phase, we implemented the whole automated workflow as a set of workers deployed on Amazon ECS to process hundreds of files.

Transformation: Now the process really started off. We can now migrate any part of the legacy application with full control over the workflow. Essentially, in this example, we wanted to migrate to Blazor, which required decomposing the frontend from the backend, and this architectural step was supervised and partially implemented by developers. In fact, GenAI-enhanced modernization is not a magic box where you put old code and retrieve the modernized one. No, it requires a lot of manual effort, but GenAI simplifies and speeds up the process significantly. We used the automation tools (prepared in previous steps) to:
- Migrate frontend to Blazor.
- Convert ADO.NET calls to Entity Framework.
- Replacing SQL native calls with the repository pattern.
- Auto-generating DTOs, basic controllers, Swagger documentation, and tests.

Human-in-the-Loop Review: This is critical. Developers must verify and fix the code—it’s never fully accurate, and sometimes, it’s even non-compilable. We can then use off-the-shelf tools to fine-tune the outcomes, fix errors, and generate additional tests.
The result? A scalable, maintainable architecture with clear documentation and test coverage — achieved in a fraction of the traditional time. What the “fraction” means depends on the technology. In this case, we not only saved a significant amount of time but also avoided the frustration of the teams forced to read and run a tedious process of migrating components one by one.
Real-World Scenarios
We’ve done quite a lot of interesting experiments, proof-of-concepts, and real, working migrations using the above approach. A couple of examples:
- Generating unit tests for a complex PHP-based system based on a microservices architecture. We have strongly used the pattern matching approach, which means using previously created unit tests to create new ones.
- Migration of hundreds of stored procedures to .NET 8. This is usually complex due to the internal structure of the procedures – lots of queries using various custom functions which… run additional queries. Copying the procedures’ code directly to .NET is not a solution, since it is just changing the platform (lift & shift), but the technical debt remains in the code.
- Migrating a WPF application to a custom Blazor implementation. This project was complex since the expected outcome was a custom, not typical, Blazor app. Pattern matching was also an approach of choice here.
Challenges and Considerations
Despite its transformative potential, GenAI-assisted modernization is not without challenges:
- LLM Hallucinations: AI can make up facts — the prompts must be prepared with care, the guardrails should be very specific, and – finally – we need to use the right LLM for the job with the correct parameters (like temperature). But we must accept the fact that hallucinations will appear anyway.
- Security and Compliance: Human review remains essential, especially in regulated industries. There is also a valid concern about code protection when using cloud-based models—it is important to understand how data protection in the cloud works.
- Skill Gaps: Teams must understand how to effectively interact with GenAI. And it is not a simple task!
- Iterative Process: Modernization isn’t “one and done” — the modernization workflow requires continuous refinement.
Conclusion
GenAI doesn’t replace developers — it empowers them. By automating the tedious, error-prone aspects of modernization, GenAI enables teams to focus on architecture, business logic, and innovation.
Instead of spending months reverse-engineering undocumented code or refactoring by hand, developers can work alongside intelligent assistants that handle the grunt work at scale.
Modernization no longer has to be a risky, painful journey. With GenAI, it becomes a manageable, iterative, and even exciting process — delivering value faster, safer, and smarter.
As enterprises look to stay competitive, modernizing legacy systems is no longer optional. GenAI isn’t just a helpful tool in this journey — it’s a game-changer.
Learn more about our AI-Native SDLC Engineering solution.
Contact