Migration & Modernization

Getting Mainframe Reverse Engineering Right at Scale

Introduction

You are about to rebuild a mainframe application that has run your organization for 30 years, and here is what most teams underestimate going in: the rebuild is not the hard part. Knowing what you are replacing is.

A mainframe estate holds thousands of business rules. They are spread across legacy languages it was built in, alongside JCL that sequences every batch job and the data structures every program depends on. Before your team begins migration to the cloud and writes a single line of new code, one question has to be answered completely, traceably, and reproducibly. What the system does.

Get that wrong, and every failure shows up after go-live, when it costs the most to fix. This post is for the architects, modernization engineers, and technology leaders responsible for getting that answer right. Five properties determine whether your mainframe reverse engineering output is something your team can build on, or something that will fail in production:

  1. Determinism: Same logic on every run. Run it twice, get the same rules.
  2. Completeness: Reads the whole estate. Every language, batch flow, and data contract.
  3. Traceability: Every rule maps to a source line, mechanically. Not prose that an auditor cannot follow.
  4. Consumable output: Formal requirements, ready to build. Not narrative that your team will need to translate.
  5. Foundational data: A data dictionary and lineage. Know what every program reads and writes.

Determinism is the quiet one. Invisible in a single run, which is exactly why most tool evaluations never catch it. This post gives it particular attention, then shows what all five properties look like measured on a real codebase, and how the resulting requirements flow into forward engineering.

The problem isn’t the rebuild. It’s knowing what you’re replacing.

Consider what lives inside a mainframe application: business rules, validations, and processing logic live in COBOL, PL/I, Easytrieve, and Natural programs. Batch scheduling rules live in JCL. Low-level utility behavior lives in assembler. Shared data structures live in copybooks. Business logic is distributed across all of it. None of those layers announce itself as critical until something in production breaks.

A mainframe reverse engineering tool that reads only part of the system produces a catalog that looks complete while silently omitting the rest. Your team builds from what appears to be a full picture, discovers the gaps later, and fixes them when the issue is already affecting end customers. The question is not whether your mainframe estate has logic spread across multiple layers – it does. The question is whether your mainframe reverse engineering approach captures all of it, automatically, on every run, in a form your team can build from.

Why your general-purpose AI coding tool isn’t built for this

Most teams point a general-purpose AI coding tool at this problem. These tools are capable, but they were not purpose-built for mainframe reverse engineering, and the gaps show up in production. Here is where they fall short:

  1. Incomplete coverage. General-purpose tools produced incomplete rule extraction across COBOL, JCL, assembler, and copybooks, with no indication that anything was missing from the output. Your team can prompt the tool to cover additional file types, but that requires first knowing what was missed, which is itself discovery work. For an organization with thousands of programs and multiple developers, this effort compounds with codebase size, and every developer would write a different prompt, producing inconsistent output with no shared baseline.
  2. Inconsistent and unstructured traceability. Some extracted rules carry line references in a free-text field; others carry none. A forward-engineering coding agent cannot consume natural language references programmatically, and your team cannot verify coverage at scale without reviewing every justification field one by one. Without complete, machine-readable traceability on every rule, the onus is on your team to reconstruct the audit trail, diverting time from the migration into work the tool should have handled. In a regulated industry, even one unmapped rule stalls a compliance sign-off.
  3. Non-deterministic output. Run the same tool twice on the same source code and rules carrying real business logic are present in one run and absent from the next. Nothing in the output signals that logic was lost. The gap surfaces only later, after weeks of building, when something does not work and the team traces back to a specification that was never complete. The migration that was meant to accelerate the journey to cloud becomes a source of rework.
  4. Non-consumable output. General-purpose tools produce rules that describe what the system does, but not formal requirements with identifiers, acceptance criteria, and traceability mappings that a coding agent can implement directly. Before forward engineering can begin, your team must convert extracted rules into structured requirements. This adds a translation step that consumes time and introduces risk that logic is lost along the way.
  5. No data foundation. They produce incomplete or no data lineage, and data dictionaries that lack field-level business definitions needed for schema migration. Your team cannot plan how data flows from the legacy system to the cloud without understanding which programs read and write which datasets. They must also know how JCL routes data between jobs and what each field means in business terms. Without this foundation, your team would have to reconstruct the data layer across the entire estate, diverting time from the migration into discovery work the extraction tool should have delivered alongside the rules.

None of these gaps show up in a demo. They surface at production scale, when the estate has thousands of programs across multiple languages and the cost of rework compounds with every week of building on an incomplete foundation. The rest of this post defines the bar that a mainframe reverse engineering approach must clear and shows what clearing it looks like.

Five properties separate output you can build from

Miss one of these five properties and your team spends time closing gaps before a single line of new code can be written. Clear all five and the output moves directly into forward engineering, with no reconciliation step in between.

What clearing the bar looks like in practice –

To make these properties concrete, AWS Transform for mainframe and general-purpose AI tool was run against CardDemo. AWS CardDemo is an open-source mainframe demo application that comprises COBOL, JCL, assembler and multi-component complexity.

In a single run, AWS Transform for mainframe processed 314 files across COBOL, JCL, assembler, BMS, and produced 153 business rules across 10 business functions. It completed the full pipeline from analyzing 59,327 lines of code to generate requirements in approximately 36 minutes. A general-purpose AI tool evaluated on the same codebase took approximately 75 minutes, processed only COBOL programs, and produced output that would require the team to identify and address coverage gaps for copybooks, JCL and assembler separately.

Property General-purpose AI tool AWS Transform for mainframe

1. Determinism

(the same logic on every run) A coding agent consuming either run’s output should build the same application. Without it, “we extracted the business rules” is a claim no one can stand behind.

Rule count differed by ~17% between runs on identical source code (761 vs 638). Business logics were present in one run and absent from the other, and vice versa, with no indication anything was dropped in either run. A team would have no way to know whether the output was complete or whether critical logic was silently lost. A deterministic static-analysis layer decomposed the source into content-hashed Business Rules (153 on both runs). Same input produced the same 153 Business Rules every time, making the foundational analysis reproducible by construction. Generated requirements for forward engineering remained semantically consistent and accurate across two runs.

2. Completeness

(read the whole system) A mainframe application is more than any one language. What you miss in extraction, you miss in production.

Processed COBOL only (44/44 programs). JCL, ASM, CPY were not analyzed in the same pass to extract Business rules. Batch orchestration and utility logic would require separate discovery before full coverage could be confirmed. Processed file types such as 44 COBOL, 56 JCL, 2 assembler, 21 BMS, 65 Copybooks in a single run. JCL, ASM, CPY rules were extracted alongside COBOL within the same job. 153 rules and 668 requirements organized into 10 named business functions, ready for forward engineering.

3. Traceability

(every rule maps to source, mechanically) Every rule must map to its source line in structured format. Free-text references do not scale for auditors, coding agents and your migration team.

For COBOL rules that were extracted, traceability was in structured JSON format with source lines. 57% of the codebase had no traceability because it was never analyzed. Every generated requirement mapped to business rules, and every business rule mapped back to specific source lines. Traceability was stored in structured YAML with program name, line numbers, and requirement IDs, producing a full traceability trail from generated requirements to source code.

4. Consumable output

(turning analysis into action) Extracted rules describe what the system does. Buildable requirements tell AI coding agents what to implement without ambiguity.

Produced business rules in natural language without requirement IDs or acceptance criteria. Before forward engineering could begin, a team would need to assign identifiers, define acceptance criteria. Each conversion step adds time and introduces risk that logic is lost in translation. Generated 668 EARS requirements in structured REQ-F-NNN format with acceptance criteria per rule. Each requirement organized by business function with traceability YAML mapping to source programs and line numbers. Output was ready to hand to a forward-engineering workflow without any conversion step.

5. Foundational data

(know what the data does) Without a data dictionary and lineage, schema migration cannot be planned and data flows cannot be validated.

Produced a 7,817-field data dictionary with business descriptions. Did not produce data lineage mappings. A team would not know which programs read which datasets, how JCL routes data between jobs, or how datasets map to physical files. Data dictionary numbers changed across two runs (7,817 vs 1,629). Produced an 11,236-field data dictionary with plain-language business definitions. Produced standalone data lineage: 83 program-to-dataset, 422 JCL-to-dataset, and 484 dataset-to-file mappings. Data dictionary and lineage numbers remained identical across two reruns.

These are results on one open-source application, not a guarantee for every codebase. The point is not the specific counts. The output cleared all five bars at once: deterministic, complete, traceable, consumable, and well-founded in data. The foundational layer is identical on every run against the same codebase: business rule counts, processed files, and completeness metrics. The generated requirements and business functions built on top are semantically equivalent across runs; the exact count may shift but remains semantically similar.

How the output becomes a rebuilt application

Reverse engineering is not the destination – it is the input. Each requirement carries its own traceability and describes semantically the same logic on every run. A forward-engineering team using AI coding agents can consume the EARS specs directly in the IDE. They can rebuild their workload as cloud native on AWS without re-reading the legacy code. The traceability YAML maps every requirement back to its source program and line numbers. This gives auditors a verifiable trail from the rebuilt application to the original.

The quality of this handoff to AI coding agent is capped by the mainframe reverse engineering step that produced it. Determinism, completeness, traceability, consumable output, and foundational data are not just academic properties. They are the difference between a rebuild workload a team can trust and one it cannot. Forward engineering is a subject for a future post.

The whole program rides on the first step

The reverse engineering step does not announce itself as the place where modernization programs succeed or fail – it looks like preparation, a box to check before the building begins. What it actually is: the foundation every build decision rests on. Miss one of the five properties and your team inherits manual work before a single line of new code gets written. Clear all five and the rebuild is one your team can stand behind.

The AWS Transform for mainframe service’s results show what clearing the bar looks like in practice: deterministic, complete, traceable, consumable, and grounded in data, on a real codebase, in a single run.

To go deeper on the end-to-end approach to mainframe modernization, visit Learnings from mainframe modernization in the real world, and explore AWS Transform for mainframe.

We will cover how these requirements flow into forward engineering with Kiro in a follow-up post.


About the authors