Hard sources — not covered by free tools
Also parsed — certify what free tools miss
Runtimes
After migration
We modernize the business job, not the plumbing. Same match criteria, same SOX outputs, a different execution shape: native PySpark and SQL, VSAM lookups as joins, JCL as a workflow, file-administration steps that Delta already makes unnecessary. Line-by-line Python that still reads one record at a time is lift-and-shift with a new compiler. That is not this engagement.
Estate parsed first: jobs, datasets, and field lineage before any wave is priced
One source, every target. Deterministic parsers read the estate and emit native code for the platform you pick — not COBOL rehosted on a cloud emulator.
COBOL estate → MigryX parser → native platforms
Deterministic parseAI where it helpsThe parser is deterministic: the same input produces the same output on every run. Every output is validated against the original, row by row, before go-live.
Directors who have lived through a rehost know the pattern: the bill moves from MIPS to cloud, the overnight window stays, and nobody can still explain the match criteria to a regulator or a new hire. The ask is not “COBOL somewhere else.†The ask is a system the business can operate.
COBOL on a cloud emulator. A Python while loop that still reads one policy at a time. Four mutually exclusive batch jobs left fused in one load module because that is how the load module was shipped. CICS maps copied onto a browser. A quote based on lines of code before anyone has counted how many steps are IDCAMS delete-and-define.
Same outputs, radically different execution. Exclusive JCL PARM modes become exclusive Spark jobs so you only run the path that runs today. Keyed VSAM reads become joins. SORT control cards become orderBy / groupBy. DB2 INSERT … SELECT stays set-based SQL. Delta versioning replaces six IMAGE copies. Parity on production data is the gate, not a slide.
Bring one job stream - programs, copybooks, JCL, and the control cards the JCL includes. We do not start in a generator. We start in an inventory the CIO can walk.
Jobs, steps, DD names, datasets, copybooks, DCLGENs, and control cards. Duplicates collapsed. Missing members named, not guessed.
Most “COBOL applications†are plumbing. In a production SOX earnings stream we assessed, 97 of 99 steps were SORT, SQL utilities, file admin, or gates. Two steps ran COBOL. One of those two was four INSERTs.
IDCAMS delete-redefine-reload often evaporates on Delta. Static SQL is already the target shape. The undocumented match program is modernized as joins and filters. 3270 conversation is redesign. You leave with a map, not a hope.
Set-oriented PySpark and SQL for the logic that changes a result. Row-and-column compare against mainframe output. No design opinions about “better match criteria†until today’s report still balances.
Assessed end-to-end from raw mainframe members: 76 canonical artifacts, 121 datasets, 56 producer-consumer edges. The comment header on the load-bearing program says the quiet part out loud: match criteria for earning remediation. There is no design document. The code is the specification. That is the usual case in shops this size, and it is why assessment-first is not optional.
| Job | What it actually does | On a lakehouse |
|---|---|---|
| Extract & sort | 13 steps. Pull cancelled and reinstated policies from a fixed-width file and reformat them twelve ways with SORT. No database. | Typed file read + orderBy / filter. Control-card field positions become the contract. |
| Table reload | 6 steps. Empty four DB2 tables and reload them. The COBOL program is four static INSERTs. No branching logic. |
Four independent spark.sql writes. Not one fused DataFrame pretending they share a scan. |
| SQL in cards | 20 steps. The “full earn†list is mostly SQL sitting in control-card text, executed by a DB2 utility - not COBOL. | Already set-based. Keep it as Spark SQL. Do not wrap it in a Python record loop. |
| VSAM admin | 42 steps. Delete, redefine, and reload three keyed files, each with six backup copies. Pure file administration. | Most of this disappears. A Delta table does not need DEFINE CLUSTER. Time travel covers IMAGE copies. |
| Match | 18 steps around one 2,200-line program. JCL PARM selects one of four exclusive modes (cancel/earn variants, undo, STAT extract). Shared VSAM lookups by policy number. | Python if on the parm so only one mode is submitted. Lookups as joins, not READ KEY. Per-output projection instead of one frame fanned to every DD. |
The remaining steps in that stream are condition-code gates and an unsourced extract utility driven by cards. We name gaps like that in the assessment instead of burying them in a wave estimate. That is how a director knows the quote is about their estate, not a generic COBOL compiler.
Lift-and-shift keeps four exclusive batch jobs inside one transform and hopes a column guard simulates JCL PARM. Modernization runs only the mode that ran last night, and treats a keyed READ as a join.
* One load module, four jobs. JCL PARM picks one.
LINKAGE SECTION.
01 PARM-AREA.
05 PROCESS-SW PIC X(5).
PROCEDURE DIVISION USING PARM-AREA.
EVALUATE PROCESS-SW
WHEN 'C200 ' WHEN 'E200 '
PERFORM 1000-EARN-MATCH
WHEN 'C270 ' WHEN 'E270 '
PERFORM 2000-DAY20-MATCH
WHEN 'UPRCD'
PERFORM 3000-UNDO
WHEN OTHER
PERFORM 4000-STAT-EXTRACT
END-EVALUATE.
* Inside a match paragraph: keyed VSAM lookup
MOVE POL-KEY TO MST-KEY
READ EARNFULL
IF WS-MST-STATUS = '00'
ADD MST-EARN-AMT TO WS-TOTAL
END-IF.
# Exclusive modes stay exclusive. Only one job is submitted.
process_sw = parm["PROCESS-SW"].ljust(5)
if process_sw in ("C200 ", "E200 "):
spark.sql("CREATE OR REPLACE TEMP VIEW earn_match AS "
"SELECT e.*, f.mst_earn_amt "
"FROM earn200 e "
"LEFT JOIN earnfull f "
" ON e.pol_key = f.mst_key")
spark.sql("INSERT OVERWRITE earn_out "
"SELECT * FROM earn_match")
elif process_sw in ("C270 ", "E270 "):
spark.sql(...) # day-20 path only
elif process_sw == "UPRCD":
spark.sql(...) # undo path only
else:
spark.sql(...) # STAT extract only
# File status '00'/'23' from the join, not from OPEN.
# PIC X stays a string. A missed key is not integer 0.
Copybooks still become typed schemas - COMP-3 unpacked at the declared scale, REDEFINES kept as a second view of the same bytes, OCCURS DEPENDING ON as variable length. That is the data contract. The procedure is modernized as set operations on top of it.
Every construct is classified in the lineage report so a wave plan is a map, not a leap.
| Mainframe construct | Target shape | Decision |
|---|---|---|
| Copybook / FD layout | Typed schema and reader | Modernize - offsets from PIC clauses |
| COMP-3 packed decimal | Decimal with implied scale | Modernize - silent corruption if you treat it as text |
| REDEFINES / OCCURS DEPENDING ON | Overlay view / variable rows | Modernize - overlays kept, not dropped |
| Level-88 names | Named predicates | Modernize - value sets become filters |
| JCL PARM exclusive modes | Python if / separate jobs | Modernize - do not fuse four jobs into one scan |
| VSAM keyed READ | Join + file-status analog | Modernize - not a per-row READ |
| Sequential READ / WRITE | DataFrame in / projected out | Modernize - WRITE FROM copies the source record |
| Static EXEC SQL INSERT/SELECT | spark.sql | Modernize - already set-based |
| SORT / SUM control cards | orderBy / groupBy | Modernize - field positions are the spec |
| IDCAMS DEFINE/REPRO/IMAGE | Usually nothing | Evaporate - Delta create/replace + time travel |
| JCL step order & COND | Workflow tasks and gates | Modernize - the schedule is the product |
| CICS 3270 conversation | Service + new UI | Redesign - not a screen scrape |
| GO TO spaghetti / SEARCH ALL | Assisted or manual lane | Named in readiness - never silently dropped |
Until the new pipeline produces the same cancel, reinstate, and earn-match results the old one produces - on real volumes, at the tolerance operations already live with - nobody is entitled to “improve†the match criteria. MigryX Data Matching compares row by row and column by column. Packed decimal and implied scale are why that compare exists.
See how Data Matching works →No. Rehosting keeps the batch window. Line-by-line Python that still processes one record per loop is the same program. We modernize the job as set operations, evaporate administration Delta already covers, and run only the PARM path that ran last night.
One job stream: programs, copybooks, JCL, control cards. Complete copybooks matter more than complete programs. A missing or mismatched copybook means every field is read at the wrong offset, which is worse than a crash - it is a quiet wrong number in a SOX report.
Because in the earnings pipeline above, COBOL was 2 of 99 steps. Pricing from lines of procedure division would have missed 42 evaporating IDCAMS steps, 18 SORT cards, and 18 SQL cards that already are the target language. Assessment first is how the number on the SOW stays related to the work.
Batch and the data layer are modernized as Spark and SQL. CICS screen interaction is reported for redesign. A 3270 conversation copied to a browser is lift-and-shift of the interface, which is the outcome most architecture boards have already rejected.
No. Deterministic parsers read the copybooks, JCL, and procedure divisions and emit Spark and SQL — the same input produces the same output on every run, which is what an auditor signs off on. MigryX AI resolves undocumented logic, and every change it makes goes through the same parity checks. It runs on a model you approve, air-gapped if your estate requires it. An LLM pasting COBOL into a prompt is not this engagement either.
Ninety minutes, on-premise or in your tenant: we parse what you send, walk the producer-consumer graph, and mark evaporate / modernize / redesign in language a steering committee can take. No compiler demo that hides the plumbing.
Book the working session →