Reading Code Nobody Can Read Anymore: Migrating RPG to .NET with AI
by Lucas, SWE Technologist
Somewhere in your company, an AS/400 is quietly doing its job. It closes the books, prices the orders, runs the warehouse. It has done so for twenty-five years with an uptime record your cloud stack would envy.
The machine is not the problem. IBM i is a stable, actively maintained platform. The problem is the code running on it: hundreds of thousands of lines of RPG, written over decades, documented nowhere except in the heads of the people who wrote it. And those people are retiring.
The spec is the code
Most legacy rewrites fail the same way. A team is hired to "rebuild the system on a modern stack." They ask for the specification. There isn't one — there never was. So they re-derive requirements from interviews and screenshots, build for eighteen months, and ship a system that gets the happy path right and the edge cases wrong.
The edge cases are the system. Twenty-five years of business decisions live in that code: rounding conventions, fiscal exceptions, grandfathered pricing, workarounds for problems nobody remembers having. Miss one and finance discovers it at month-end close — after cutover, when there is no going back.
That is why the honest options have always looked bad. A big-bang rewrite bets the company on a spec that doesn't exist. Doing nothing bets it on the retirement date of your last RPG programmer.
What AI actually changes
Until recently, the expensive part of a migration was reading. Understanding a large RPG estate meant either the original authors — increasingly unavailable — or months of specialist archaeology at consulting rates.
Large language models read fixed-format RPG, free-format RPG, DDS, CL, and COBOL fluently. They trace call graphs, map file access, and turn programs into structured descriptions of what the business actually does. Archaeology becomes cheap. The bottleneck moves to validation — and validation is a much better problem to have, because your own team can do it.
A walkthrough on sample code
Take this fragment — a simplified version of the order-pricing logic we find in most AS/400 estates:
C CUSNBR CHAIN CUSMST 90
C IF *IN90 = *ON
C EVAL DISCPC = 0
C ELSE
C EVAL DISCPC = 0
C IF CUSTYP = 'W'
C IF ORDVAL >= 25000
C EVAL DISCPC = 12
C ELSE
C EVAL DISCPC = 8
C ENDIF
C ENDIF
C IF CUSDAT < 20200101
C EVAL DISCPC = DISCPC + 2
C ENDIF
C ENDIF
Step 1 — extract the rules. AI reads the program, the DDS for CUSMST, and every caller, and produces the rules in plain language:
- Wholesale customers (
CUSTYP = 'W') receive a base discount of 8%. - Wholesale orders of 25,000 or more receive 12% instead.
- Customers onboarded before January 2020 receive an additional 2 points — a grandfathered loyalty bonus that appears in no policy document.
- If the customer record is missing, the discount silently falls to zero. Bug or rule? The code cannot say. A person can.
That last line is the point. AI does not replace the specialist who validates the rules — it compounds them. Instead of reading four hundred thousand lines, they answer the specific questions the analysis raises.
Step 2 — document. Every program gets a generated dossier: purpose, inputs and outputs, files touched, business rules, open questions. A subject-matter expert reviews it, resolves the open questions, and the answers are recorded. This deliverable has value even if the migration stopped here — for the first time, the system is written down.
Step 3 — rebuild. With validated rules, the module is rebuilt on the target stack. The C# is unremarkable, which is exactly the goal:
public decimal DiscountPercent(Order order, Customer? customer)
{
// Missing customer record means no discount. Confirmed with
// operations: a deliberate rule, not a defect.
if (customer is null) return 0m;
var discount = 0m;
if (customer.Type == CustomerType.Wholesale)
discount = order.Value >= 25_000m ? 12m : 8m;
// Grandfathered loyalty bonus for customers onboarded before 2020.
if (customer.OnboardedAt < GrandfatherCutoff)
discount += 2m;
return discount;
}
Step 4 — run in parallel. The new module receives the same production inputs as the old one, and the outputs are reconciled automatically. Every divergence is either a rule the extraction missed or a defect the rebuild fixed — and each one gets classified, not guessed at. The module is promoted only after reconciliation runs clean for an agreed window.
Step 5 — sequence, don't big-bang. Repeat module by module, ordered by risk and business value — the strangler pattern. The AS/400 keeps running everything that hasn't moved yet. There is no cutover weekend, because there is no cutover.
What survives
The deliverable of a migration run this way is not just a new system. It is the system's knowledge, extracted and written down while the people who could confirm it are still in the building. The business rules stop living in one retiring engineer's memory and start living in documentation, tests, and reconciled outputs.
This is the method behind the Legacy Assessment on our Build & Run practice: ninety days, fixed scope — full inventory of the estate, AI-generated documentation of the business rules, a sequenced migration roadmap, and one module rebuilt and running in parallel as proof. The assessment stands on its own. If the migration follows, FSK takes it on by contract and risk.