What’s the Hurry About Modernizing
Legacy modernization sat on enterprise roadmaps for a decade without moving much. Four things changed that.
- The knowledge is leaving faster: The engineers who know why a routine exists, the regulation it was written for, the incident it was patched after, are retiring and cannot be replaced.
- Cybersecurity alarms cannot be kept on snooze: Exploiting vulnerable software has become exponentially easier. No enterprise can afford vulnerabilities.
- Integration cost is compounding: Every new integration request demands a feature that is difficult to build.
- AI Native needs modern systems: The push to deploy AI across the enterprise runs straight into legacy systems no model can read and no team can safely change.
Gartner's forecast on mainframe exit programmes is worth reading against that list. The pressure to move is now considerably higher than the confidence to move, and that gap is where most modernization budgets are currently sitting, unspent.
The root difficulty is not technology. It is knowledge. Documentation describes what the system was supposed to do. The code describes what it actually does. Over twenty years those diverge, and only the second one is in production.
THE REAL QUESTION
Not "how do we build the new system?" but "how do we change the system without accidentally changing the business behaviour buried inside it?"
AI makes the first question much easier. It leaves the second one exactly where it was.
Modernizing Applications Is More Than Building Features
Coding agents are genuinely good at new feature work. Modernization is a structurally different problem, and the difference is not one of scale.
| Feature development | Migration |
|---|---|
| Starts from desired behaviour | Starts from existing behaviour |
| Requirements define the outcome | Existing behaviour defines the outcome |
| Implementation designed freely | Implementation constrained by real dependencies |
| Tests validate intended behaviour | Tests must first establish existing behaviour |
| Context is forward-looking | Context must be reconstructed from the past |
| AI generates | AI must understand before it transforms |
Why the pilot always looks fine
This is the pattern that repeats. A team runs an AI migration pilot on a well-chosen module of a few thousand lines. It goes beautifully. The programme is approved on that evidence, and somewhere past a hundred thousand lines it stalls, not with failures, but with a steering committee that can no longer say what percentage is actually done.
The pilot succeeded because a human still held the whole module in their head. That is the variable that does not scale.
A FAMILIAR SHAPE
Every team that has done this has a version of the same story. A function that static analysis says nothing calls. It is in fact invoked by name, from a value in a configuration table, by the end-of-day job. Remove it and every test still passes. Month-end reconciliation fails three weeks later, and by then twelve other things have changed.
An agent pointed at that repository can write excellent code. What it cannot do unaided is answer the questions that decide whether the migration is safe:
- Which behaviour here is essential, and which is incidental?
- What actually reaches this code at runtime?
- Why do these two modules share a table, and what breaks if they stop?
- Is this difference between old and new an improvement, or a regression?
The Missing Piece Is Not a Better Model or the Agent
Model capability is improving quickly and is not what blocks these programmes. What is missing is a layer beneath the agent: an evidence-backed model of the application, covering structure, real dependencies, interfaces, data ownership, workflows, batch and scheduled processes, configuration surface, integrations and behavioural contracts, and the relationships between all of them.
Retrieved snippets are not that. To be usable, the model has to hold five properties.
- Semantic: Meaning and relationships, not text matching.
- Connected: Components understood inside the whole. Local correctness is not system correctness.
- Traceable: Every conclusion resolves to a file and a line. An untraceable finding is an assertion.
- Persistent: Reused across the programme, not rebuilt per slice and quietly drifting.
- Current: It evolves as the application does.
The layer between a coding agent and a system it has never seen.
Understanding alone still is not enough. A migration also needs a disciplined way to fix what must be preserved, transform incrementally, and prove the result at each step.
How Vyazen Runs a Migration
No stage opens until the previous one is formally accepted.
Understand, then baseline
Vyazen indexes the running application and derives its real architecture, dependencies, workflows, data ownership, integrations and batch surface, every finding traceable to source, because the existing code is the specification and the documentation stopped being true years ago.
Only then is "correct" established: the application run and validated, coverage and performance measured, and characterisation tests built around existing behaviour and proven green against the old system before any migration code is written. The reference point is the running application, not a model's reconstruction of it. Behavioural parity becomes the default acceptance standard.
Design, then migrate in waves
The target architecture is defined with dependency boundaries that will be machine-checked later, data ownership and schema transitions resolved, and the application decomposed into slices ordered into dependency-aware waves. Intended behaviour changes are recorded and approved in advance.
That last point carries more weight than it appears to. If the new system behaves differently, there is one question: was the difference declared beforehand? If yes, it is an approved change. If no, it is a defect and it does not quietly become part of the new system. This is the operative line between a defect and a change request, and it removes the most common source of dispute in migration programmes.
Every component of the original enters an accounting record and must resolve to a defined state: migrated, merged, deliberately dropped, or explicitly deferred with approval. Completion becomes arithmetic rather than an estimate.
Verify on two axes
Passing one axis and failing the other is the most expensive outcome.
Behavioural: Same results, preserved validation rules and error conditions, preserved database effects, working integrations, correct workflows and batch cycles.
Structural: Dependency boundaries respected, no new coupling, no circular dependencies, no unreachable code. Does the system that was built resemble the one that was designed?
The second axis matters because a migration can achieve complete behavioural parity while faithfully recreating the architectural problems of the legacy system in a newer language. That is not modernization. That is the next migration, rescheduled. So the migrated code is re-indexed as each wave lands and compared against the approved target, drift is caught in the week it appears, not at handover.
The Takeaway
Modernization was never bottlenecked on code generation. It was bottlenecked on two questions that AI does not answer by itself: what does this system actually do, and how would we know if the new one stopped doing it?
That changes what to ask a vendor. Not how much of the codebase their agent rewrites per week and that number will keep improving for everyone, and it was never the constraint. Ask instead:
- How do you establish what the existing system does, and can you trace any claim back to a line of code?
- What is the acceptance test, who wrote it, and was it proven against the old system before migration started?
- At any point in the programme, what percentage is complete and is that a count or an opinion?
- At handover, what do I give my auditor?
A vendor who cannot answer those is selling code generation. You know that won't be enough.