
Nobody starts a project hoping to work on legacy code. You dream of greenfield. Clean architecture, modern frameworks, no decisions to regret because nobody's made any yet.
Then a client calls and says "we've got this system" and you know from the pause that follows that you're about to meet something special.
I've spent a lot of my career working with older .NET codebases. They're load-bearing walls. The team that built them left years ago. The documentation, where it exists, is aspirational at best. There are DLLs nobody can account for, but that's a problem for another day. The point is: they work. They've worked for years. And the business would very much like them to keep working, please.
These systems don't get blog posts written about them. They're not glamorous. But they're where some of the most interesting AI-assisted work is happening right now.
The First Date
There's a specific moment when you point an AI tool at a legacy codebase for the first time. A brief, hopeful pause, followed by what I can only describe as polite confusion.
AI models expect modern patterns. Clean separation of concerns, current frameworks, recent conventions. Hand them a WebForms application with business logic in the code-behind and SQL built by string concatenation, and they do their best. But their best often assumes a world where everything was built last Tuesday, and there are zero constraints on what you can do today.
The suggestions come back technically correct and completely impractical. Yes, this should be refactored. Yes, those queries should be parameterised. Yes, that pattern is outdated. But I'm not here to rewrite the architecture. I'm here to make a change that works, ships, and doesn't break the thing that's been running the business since before anyone in the room was hired.
Making It Work
The trick is giving the AI the right context about the world it's actually operating in. Not the world it expects. The world that exists.
You're not just providing requirements. You're providing history. Constraints that exist for reasons nobody documented. Patterns that look wrong by modern standards but are correct for this system because of decisions made years ago that can't be unwound without breaking things.
"Don't suggest replacing this. We can't. Here's what we can do. Here's the boundary. Work within it."
Framed that way, AI becomes remarkably useful. It can modernise a single component while respecting the architecture around it. It can write tests for code that never had any. It can help you understand what a thousand-line method actually does when the only comment is // TODO: fix this later from 2014.
It doesn't get intimidated by ugly code. It'll read the whole thing, map the logic, suggest a path forward. It's patient in a way that humans aren't with codebases like these. Paired with someone who knows which bits are fragile and which are solid, who can tell whether a suggestion is safe or catastrophic, it's a genuinely powerful combination.
The AI brings capability. The experience brings judgement. The legacy codebase brings humility for everyone involved.
The Long Game
Every modern system is just a future legacy system that hasn't aged yet. The patterns we're building today will look dated in ten years. Someone will inherit them and sigh.
The skill that lasts isn't knowing the current best practice. It's knowing how to work with what's actually there, understanding why it ended up like that, and improving it without breaking the thing that's been quietly keeping the lights on.
Legacy code isn't a problem to be solved. It's software that survived. Treat it with some respect, bring the right tools, and there's genuinely brilliant work to be done.
This is also why pointing a prompt at a legacy codebase and hoping for the best is a recipe for making things worse, faster. AI amplifies in all directions. It can accelerate good decisions and bad ones equally. Understanding the wonderful, detailed explanation AI generates is one thing. Knowing which of those moving parts actually matter, which can safely be changed, which absolutely shouldn't be touched, and what the impact of each change will be across the wider system, that takes experience. The prompt that worked on the last project is a starting point, not a playbook. Every legacy codebase is its own unique beast, that once was a masterpiece, and navigating it well is still a human skill.