Skip to main content
Back to Blog
Should You Let an Agent Modernize Your Legacy .NET?

Should You Let an Agent Modernize Your Legacy .NET?

4 min read600 views0 likes
#dotnet#github-copilot#modernization#legacy-code#engineering-management

A checklist before pointing GitHub Copilot's modernization agent at a legacy codebase: test coverage as a prerequisite, review capacity as the real constraint, and what to keep humans in front of.

Microsoft shipped a modernize-dotnet agent for GitHub Copilot that runs the same upgrade workflow across Visual Studio, VS Code, the Copilot CLI, and GitHub itself. Point it at a legacy codebase, get an assessment, a plan, and a set of code changes.

I lead an engineering organisation that maintains .NET services in a regulated healthcare environment, so a tool like this lands on my desk as a buy-versus-build question, not a demo. Here is the checklist I'd work through before letting an agent loose on a legacy codebase, and the conditions under which I think it genuinely pays.

The Prerequisite Nobody Mentions

An agent that rewrites your code is only as safe as your ability to tell whether it broke something.

If your test suite is thin, an automated upgrade doesn't save you work — it relocates the work to production, where it costs more. The honest sequence is: get integration coverage on the critical paths first, then modernize. Not the other way round.

This is unglamorous and it's why many modernization efforts stall. Teams want the upgrade because the upgrade is visible. The coverage that makes the upgrade safe is invisible until it saves you.

A reasonable bar before starting:

  • The critical paths have integration tests that run against real dependencies, not mocks.
  • Those tests run in CI on every commit, and the team trusts them enough to block a merge.
  • You can deploy and roll back without a meeting.

If all three are true, an upgrade agent is a genuine accelerator. If none are, it's a way to generate a large diff nobody can review.

Review Capacity Is the Real Constraint

The failure mode I'd worry about isn't the agent writing bad code. It's the agent writing a lot of plausible code.

A framework upgrade across a mature codebase can touch hundreds of files. A human reviewer faced with a 400-file diff does not review it — they skim it, spot-check a few files, and approve. That's not review, and everyone involved knows it.

So the thing to insist on is scoping. One project at a time. One category of change at a time. Small enough that a reviewer can genuinely read it and form an opinion. If the tooling encourages a single sweeping change, impose the boundaries yourself.

The question to ask of any agentic change isn't "is this correct?" but "can somebody here verify whether this is correct?" Those are different questions and only the second one is about your team.

Where It Earns Its Keep

Mechanical, repetitive, well-specified transformations. Target framework bumps. API migrations where the old and new shapes are known. Dependency updates with predictable breaking changes. Configuration format moves.

These are tedious, error-prone when done by hand, and exactly where a tool with a full view of the codebase outperforms a human doing it file by file at four in the afternoon.

Where I'd Keep Humans In Front

Anything where the right answer depends on context the agent doesn't have.

Architectural decisions dressed up as refactors. Code whose oddities encode a business rule nobody wrote down — and in healthcare there is always some of this, usually a payer-specific quirk that looks like a bug until you remove it and something breaks. Security boundaries. Anything touching data-handling behaviour where a regulator would want an explanation.

The tell is whether the code looks wrong for a reason you can't immediately reconstruct. That's often institutional knowledge wearing a disguise, and an agent optimising for idiomatic modern .NET will cheerfully remove it.

The Compliance Dimension

In a regulated environment there's an extra question: can you explain this change later?

If an auditor asks why a data-handling path changed, "the agent upgraded it" is not an answer. You need the same traceability you'd want for any other change — what changed, who approved it, what testing confirmed it, why it was needed. Agent-generated changes are not exempt from that, and if your process quietly treats them as lower-risk because they're mechanical, that's a gap worth closing before it's found for you.

How I'd Actually Run It

  1. Pick a low-stakes service first. Learn the tool's failure modes where they're cheap.
  2. Scope each run narrowly enough to be reviewable.
  3. Require the same CI gates as any change — no fast lane for automated diffs.
  4. Ship through progressive delivery, so a subtle behavioural change surfaces on a canary rather than everywhere at once.
  5. Keep a record of what was automated and what was hand-reviewed.

None of that is exotic. It's the process you should already have, applied without making an exception because the code came from a tool.

The Honest Summary

Modernization agents are a real improvement over doing this by hand. The bottleneck they remove — the sheer mechanical labour of a large upgrade — is genuinely a bottleneck.

But they don't remove the bottleneck most teams actually have, which is confidence. Confidence comes from tests you trust and changes small enough to review. A team with those will get a lot out of this tooling. A team without them will get a large diff and a bad quarter.

Source: Modernize .NET Anywhere with GitHub Copilot, Microsoft .NET Blog.

© 2026 Ahmed Shaltoot. All rights reserved.