Contact Us
Strategy August 28  •  14 min read

Why mainframe modernization projects fail

Most failed mainframe modernization projects share the same 6 decisions. Here's what goes wrong, when it becomes visible, and how to structure around it.
← All posts

Failed modernization programmes don’t usually fail at the end. They fail in month 3 and find out in month 20.

That gap is the whole problem. The decisions that determine the outcome get made early, when they look like sensible scoping choices, and the consequences surface long after the people who made them have moved on.

This piece covers the 6 decisions that show up repeatedly in programmes that don’t land, when each becomes visible, and what to do instead. It’s written from the pattern rather than from any single engagement.

One note on the statistics you’ll see elsewhere. A lot of published failure rates in this category trace back to nothing in particular, so we’re not going to add another number to the pile. The pattern is more useful than the percentage.

Failure 1: no exit condition

The most common one, and the least dramatic.

A programme starts with a goal like “modernize the core platform”. Nobody writes down what state constitutes done. The assumption is that it’ll be obvious.

It never is. Every quarter surfaces something worth including. A dependency that should be handled properly. A module that would be simpler to convert now than later. A capability the business would like while the code is open anyway.

None of these are unreasonable individually. Together they mean the finish line moves at roughly the rate the programme advances, and after 2 years the sponsor is looking at a programme that has consumed its budget and can’t say how close it is.

Visible at: month 12 to 18, usually when a budget cycle forces the question.

What to do instead. Define done as an observable state before you start. “These 340 programs and these 12 files no longer run on the mainframe, and the mainframe LPAR supporting them is decommissioned.” That’s testable. “The platform is modernized” isn’t.

Then structure in waves where each wave has its own exit condition and its own business value. A programme that retires a workload every 6 months keeps proving itself. A programme with one deliverable at month 34 is asking for 34 months of trust, and organisations don’t have that much trust.

We’ve written about this funding dynamic in how to fund modernization when there are no new features at the end.

Failure 2: verification deferred to UAT

This is the expensive one.

The plan says convert, then test. Testing is scheduled after conversion, as a phase. UAT is where correctness gets established.

Two things go wrong.

First, defects found in UAT are the most expensive defects to fix, because by then thousands of programs have been converted using the same approach that produced the defect. A single systematic error in how packed decimal arithmetic was handled means every financial program in the estate is wrong, and you find that out 14 months in.

Second, and worse, UAT doesn’t find semantic drift reliably. UAT exercises the paths business users know about. Drift lives in the paths nobody exercises: the negative packed decimal, the boundary value on a variable-length table, the record written under a field convention that changed in 1997.

Published research is direct about how hard this is to catch. A 2026 study from AWS-affiliated researchers (arXiv:2605.21537) ran 1,980 code modernization tasks across 11 production models, and found that when semantic drift was introduced, the systems that introduced it detected only 68.3% of their own errors on review. Roughly a third passed through unflagged.

Visible at: UAT, or worse, in production 6 weeks after cutover.

What to do instead. Verification runs continuously from the pilot onward, using an oracle that’s independent of whatever produced the converted code.

Production input and output capture, replayed against the converted system with field-level comparison, is the strongest option. Batch output diffing is the cheap version and works well for batch-heavy estates.

Then build a targeted suite for the constructs that are known to be trap-prone: COMP-3 arithmetic, ROUNDED semantics, REDEFINES, OCCURS DEPENDING ON, sign handling, EBCDIC collation. That’s a small suite and it finds more real defects per test than anything else you’ll run.

The Oracle BigDecimal documentation is worth putting in front of your Java team early, because the difference between exact decimal and binary floating point is where most financial drift originates.

Failure 3: the data layer treated as a subtask

Ask a programme plan how long data migration will take and you’ll often get a smaller number than code conversion. That’s backwards on most estates.

VSAM files carry implicit schemas that exist only in the COBOL that reads them. There’s no data dictionary. Reconstructing the schema means analysing every program that touches the file and reconciling the versions when they disagree, which they do, because 30 years of change leaves fields being reused for different purposes.

Then there’s access pattern. Mainframe batch is optimised for sequential record-at-a-time I/O against local files. A relational database over a network behaves nothing like that. Code converted faithfully will often run correctly and far too slowly, and “correct but misses the batch window” is a failed cutover.

The PostgreSQL numeric type documentation shows why precision needs a deliberate decision here, and Spring Batch is worth understanding early if the target is Java, because batch restructuring is usually required rather than optional.

Visible at: month 10 to 16, when the first converted batch job runs against real volumes.

What to do instead. Give data its own workstream with its own lead, starting during discovery. Reconstruct schemas early, before conversion locks in assumptions. Run performance tests on production-volume data during the pilot, not during UAT.

Budget 15% to 25% of programme cost here. Plans that allocate less are usually plans that haven’t looked at the file layouts yet.

Failure 4: redesigning during migration

The scope creep with the best intentions.

Once the code is open, redesign looks free. The team can see that this batch job should be an event stream, that this monolith should be 3 services, that this data model was a compromise made in 1996 for reasons that no longer apply.

All true. And doing it during the migration means you’ve now got 3 hard problems running simultaneously: language conversion, architecture change, and specification reconstruction, with no test suite and no rollback point.

It also breaks verification. Comparing an old system against a functionally equivalent new one is a diff. Comparing it against a redesigned one is a judgment call on every difference, made by people who have to decide whether each one is a defect or an improvement. That’s slow, and it’s where confidence goes to die.

This is a large part of why strangler fig migrations stall so consistently around the 40% mark, which we’ve analysed in why most strangler fig migrations stall at 40%.

Visible at: month 15 to 24, as the verification backlog stops clearing.

What to do instead. Preserve behaviour through the migration, then rearchitect from a stable base with a working test suite and developers who can read the code.

That sequencing is discussed at length in rehost, refactor or rearchitect. It’s 2 phases instead of 1, and it’s the version that survives a sponsor change.

Capture the redesign ideas as they come up. Put them in a backlog for phase 2. They’ll be easier to implement then, and you’ll know more.

Failure 5: business rules assumed to be documented

Somebody says early on that the business rules are documented. Everyone relaxes.

What exists is usually a functional specification written when the system was built, a set of change requests describing amendments, and a wiki. What’s missing is the accumulated behaviour of 30 years of production, which lives in the code and nowhere else.

The rules that matter most are the ones nobody remembers deciding. What happens when a policy lapses on the 29th of February. Which of 4 date fields wins when they conflict. The special case for accounts opened before 1998 that exists because of a regulatory change since superseded.

Extraction tooling helps, and the platform vendors have invested heavily here. It produces an inventory of decision logic, which is an input to understanding rather than a substitute for it. A rule extracted without its history tells you what happens, not why, and the why is what tells you whether to keep it.

Visible at: UAT, when the business says the new system is producing wrong answers and nobody can determine whether the old behaviour was correct or a long-standing bug.

What to do instead. Treat the source code as the specification, because it is. That’s an argument for translation over reconstruction, since translation carries the rules across whether or not anyone remembers them.

Keep your COBOL developers on the programme through validation. They’re the highest-value people involved, and their knowledge is the thing no tool extracts. The instinct to release them once conversion starts is exactly wrong, and it’s covered in the talent shortage for legacy code.

Failure 6: an automation percentage taken at face value

A vendor quotes 95% automation. The plan gets built assuming 5% of the work needs human attention.

Two errors compound.

The first is definitional. Automation percentages are computed differently across vendors: lines converted without edit, programs converted without edit, or programs reaching test with no human touching the output. The same project honestly reports 95% or 60% depending on which. Published industry figures cluster at 70% to 85%, up from around 40% in 2020, and almost none of them state the denominator.

The second is distributional. The residual isn’t spread evenly. It concentrates in the code with the densest logic, the most unusual constructs and the least documentation, which is exactly the code where a human needs the most time and carries the most risk.

So 5% of the volume routinely consumes 30% or more of the conversion effort. A plan that treats it as 5% of the effort is under-resourced by a factor of 6 at the hardest point in the programme.

Visible at: month 8 to 14, as the residual queue grows faster than it clears.

What to do instead. Ask one normalising question: what percentage of programs go to test with no human editing of the output? Then size the residual by effort rather than by volume, using the pilot to calibrate.

And ask how defects get fixed. If a defect in the converted output is fixed instance by instance, the residual queue never clears, because every occurrence needs individual attention. If it’s fixed at rule level, one correction propagates across the estate.

That distinction is a property of the underlying technology. Deterministic transformation, where the same input always produces the same output, allows rule-level correction because the transformation is formally specified. Semantic Designs’ DMS platform, which fuses symbolic AI with enhanced compiler technology, is built on that model, and how deterministic software transformation works covers the mechanics.

Failure 7: cutover with no exit condition

The one that turns a nearly-successful programme into an expensive stalemate.

Parallel running is correct. You run the old system and the new one side by side, compare outputs, and build confidence before switching. Skipping it is how organisations end up in case studies.

What goes wrong is starting parallel running without defining when it ends.

“We’ll run parallel until we’re comfortable” sounds prudent and has no end state. Comfort is not a measurable condition, and there’s always one more reconciliation break to investigate, one more edge case to observe, one more month-end to get through.

Meanwhile you’re paying for both platforms, staffing both operations teams, and maintaining the reconciliation process. Programmes have run parallel for 2 years this way, which erases the saving that justified the migration.

There’s a second-order effect too. While parallel running continues, the mainframe can’t be decommissioned, and decommissioning is where the financial benefit actually lands. A programme that converts everything successfully and never turns the old system off has delivered technical success and zero financial return.

Visible at: month 6 of parallel running, when someone asks why the mainframe bill hasn’t moved.

What to do instead. Define the exit condition numerically before parallel running starts. Something like: 3 consecutive month-end cycles with zero unexplained reconciliation differences above a stated tolerance, and no severity-1 incidents attributable to the new platform.

Then commit to decommissioning on a date, with a named owner. The decommission should be a scheduled deliverable with its own plan, not something that happens when everyone gets round to it.

What recovery looks like

A meaningful share of this market is second attempts, and the industry talks about it less than it should.

If you’re restarting, the situation differs from a greenfield programme in ways that matter.

You have a hybrid estate. Some workloads moved, some didn’t, and bridging code connects them. That bridging code is now load-bearing production infrastructure that nobody designed to last. It’s the first thing to inventory.

Your documentation improved. Whatever else the first attempt produced, it produced analysis. The dependency graph, the dialect inventory, the schema reconstruction work all retain value. Recover it before the team disperses.

Trust is lower. The second business case faces harder questions than the first. This argues strongly for a waved approach with early, visible delivery, because the programme has to re-earn credibility it spent.

The estate got harder. Partial migration usually means the easy workloads went first. What’s left is the difficult residue, and estimating it against the velocity from attempt 1 will understate it.

Practical sequence for a restart:

  1. Inventory the hybrid state, including every bridge and every interim data flow.
  2. Recover the analysis assets from attempt 1.
  3. Reassess complexity on what remains, not on the original estate.
  4. Decide explicitly whether to complete the original approach or change it, and write down why.
  5. Re-wave from where you are, with the first wave sized to deliver inside 6 months.

Point 4 is the one people skip. Continuing a failed approach because of sunk investment in tooling is how second attempts become third attempts.

The pattern underneath all 7

Read them together and a single theme emerges. Every one of these is a decision to defer a hard problem to a phase where it costs more to solve.

Exit conditions deferred to when the money runs out. Verification deferred to UAT. Data deferred to after conversion. Specification reconstruction deferred to when the business complains. The residual deferred to when it’s blocking everything.

Modernization programmes don’t fail because the technology doesn’t work. Automated conversion has been running production systems for decades. They fail because the schedule was built around the phase that’s easiest to estimate, and the phases that carry the risk were left as assumptions.

The fix is unglamorous. Front-load the assessment. Verify continuously. Give data its own workstream. Preserve behaviour now and redesign later. Keep the people who understand the system. Size the residual by effort.

None of that is a technology decision. All of it is decided in the first 3 months.

Governance that actually catches these

Steering committees are usually briefed on percentage complete, which is the least informative metric available on a modernization programme. Percentage complete measures conversion, and conversion isn’t where the risk lives.

Five metrics that surface the failures above while they’re still cheap.

Put these on the steering pack and most of the failures in this piece become visible 6 to 9 months earlier than they otherwise would.

A pre-mortem checklist

Before the programme starts, answer these in writing. If more than 2 are uncomfortable, the plan needs work.

  1. What observable state means this programme is done?
  2. What’s our oracle for correctness, and is it independent of the conversion?
  3. Who owns the data workstream, and when do they start?
  4. Are we preserving behaviour, or redesigning? Where is that written down?
  5. Which COBOL developers are committed through validation, and are they contracted?
  6. What percentage of programs will reach test with no human editing, by the vendor’s own definition?
  7. Are defects fixed at rule level or instance level?
  8. What’s each wave’s independent business value?
  9. What’s our rollback plan at cutover, and how long can we run parallel?
  10. What happens to this programme if the sponsor changes in month 18?

Question 10 is the one people skip. It’s also the one that predicts the outcome best, because sponsor tenure in most organisations is shorter than a large modernization programme.

The counter-pattern: what working programmes do differently

Worth stating positively, because the failure list can read as discouraging and it shouldn’t.

Programmes that land tend to share 5 characteristics.

None of that is novel and none of it is expensive relative to the programme. It’s mostly a matter of resisting the pressure to compress the phases that don’t produce visible output.

The pressure is real. Assessment looks like delay, test harness construction looks like overhead, and parallel running looks like waste. Every one of them is the thing that makes the rest work.

Frequently asked questions

What percentage of mainframe modernization projects fail?

Widely quoted figures exist and most trace to no verifiable source, so treat them carefully. The more useful observation is that failures cluster around a consistent set of early decisions rather than around technology limitations.

Is failure more common with automated or manual approaches?

Manual approaches carry higher cost and longer timelines, which increases exposure to sponsor change. Automated approaches fail differently, usually through unverified output reaching production. The verification plan matters more than the automation choice.

Can a failed programme be restarted?

Yes, and it’s more common than the industry admits. The second attempt inherits a partially converted estate with bridging code, which is harder than the original. Assessment before restart is worth more than it was the first time.

How early can you tell a programme is in trouble?

The pilot, if it’s designed to find the boundary rather than to succeed. A pilot on representative hard code surfaces most structural problems within 12 weeks.

Does Gen AI reduce failure risk?

It helps in discovery, documentation and test drafting, where output is reviewed by a human and errors are visible. Putting generation on the critical path to production without independent verification adds risk rather than removing it, which we cover in why Gen AI alone is not enough for modernization.

What’s the single best predictor of success?

Whether verification starts at the pilot or after conversion. Programmes that verify continuously catch systematic errors while they’re cheap to fix.

Next step

Most of the failures above are visible during assessment, before any money is committed to conversion.

Modernize Software runs a free codebase assessment that inventories the estate, maps dependencies, identifies dialects and flags the constructs that carry conversion risk. It’s the cheapest phase of any programme and the one that most improves everything after it.

The modernize COBOL hub covers the transformation approach, and the DMS platform page explains the technology underneath it.