Modernization Strategies
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against ISO/IEC 1989:2023 (edition 3, January 2023; an upcoming 4th edition is in ballot), against
IBM Enterprise COBOL for z/OS 6.5 (PTFs through September 2026) on z/OS 3.2, and against GnuCOBOL 3.2 (28 July 2023,
the latest release). The only program on it was compiled with cobc -x -Wall -std=ibm and run on 2026-10-20. z/OS
facts are taken from the IBM documentation listed under References and are labelled "z/OS; not run here".
Modernization is not a language topic, it is a decision about a system: the Circulation back office (BOOKMAST,
MEMBMAST, LOANTRAN, the nightly batch run and the CICS CINQ inquiry) works, the people who understand it are
retiring, and the business wants new channels. This page lists the options, shows how the strangler-fig technique from
Migration Path: Legacy to Modern Stack
applies to a mainframe, describes what IBM’s watsonx Code Assistant for Z is documented to do, and ends with the data
traps that decide whether a migration succeeds. The language-level side (obsolete statements, compiler moves) is on
Legacy Features and Migration; the environment is in
Mainframe Environment Primer.
Where the book is outdated: Taulli’s Modern Mainframe Development (2022, chapters 10 to 13) was consulted for the topics only: its modernization options (hybrid cloud, encapsulation, rehost and replatform, refactor and rearchitect, replace), AI/ML and RPA on the mainframe, and Mainframe as a Service. Its product names and release numbers date from 2021 and 2022 (Enterprise COBOL 6.3, z/OS 2.4, Db2 12, CICS 5.6, the z15, Micro Focus as a separate company), and generative-AI assistance for COBOL, which now exists as a product, is not in it. The current facts are in What’s New in COBOL.
The options
Every option answers the same question differently: how much of the code, the data and the platform changes?
| Option | What changes | What stays | Fits when |
|---|---|---|---|
Keep and extend (encapsulate) |
Add APIs in front of existing programs: CICS web services or z/OS Connect for REST and JSON, MQ messages, IMS Connect. New work is written elsewhere and calls in. |
The COBOL, the data, the batch window, the platform. |
The code is sound and the cost is in access, not in the logic. The usual first step. |
Rehost (lift and shift) |
The platform: the same compiled or recompiled COBOL, JCL and CICS definitions run on an emulation or compatible runtime on Linux or in a cloud (Rocket Software’s Enterprise Developer and Enterprise Server family, formerly Micro Focus, is one example; the cloud providers sell managed offerings). |
The source, the data formats, the job structure. |
The goal is to leave the hardware or the licence, and the team accepts a different runtime with the same programs. |
Replatform |
The platform plus parts of the stack: Db2 for z/OS becomes another relational database, VSAM becomes files or a database, JCL becomes a scheduler. |
The COBOL logic, with edits where dialects differ (see Legacy Features and Migration). |
The estate is portable code with limited mainframe-only features. |
Refactor |
The code: cleaned up, restructured, sometimes translated to Java (automated translation or AI assistance). Behaviour is meant to stay identical. |
The business rules and the data model. |
The logic is valuable but unreadable, and tests (or a parallel run) can prove equivalence. |
Rearchitect |
The design: the monolith is cut into services around business capabilities, data is split, batch becomes events. |
The business rules, rewritten or ported service by service. |
The business changes faster than the monolith can follow. |
Replace |
Everything: a commercial package or a new system takes over, the COBOL is retired. |
Nothing, except the data, which must be migrated. |
The application is a commodity (payroll, a standard library system) and a product fits. |
Two points are easy to miss. First, the options combine: a typical plan encapsulates now, strangles the highest-change areas next, and rehosts what is left. Second, there is a sixth answer that is a decision rather than a project: leave it alone. A stable batch job with no change requests costs little, and the risk of a rewrite is larger than the risk of keeping it. Taulli’s chapters on hybrid cloud and Mainframe as a Service describe the middle ground, where the mainframe stays and a managed provider operates it.
Keep and extend: expose COBOL as APIs
The cheapest modernization is to make the existing program callable. The program does not change; a layer in front of it translates between JSON over HTTP and the record layout of a copybook.
-
CICS. A CICS program that follows the pattern in CICS Online Programming (a service program using a
COMMAREAor a channel, a separate screen program) can be exposed as a web service or JSON resource by mapping the copybook to JSON. The service program must not do terminal I/O and must return an error code instead of abending; theCIRCAVLandCINQsplit on that page is built for this. CICS Transaction Server 6.x documentation is at IBM CICS TS 6.x documentation. -
z/OS Connect. A gateway that exposes z/OS programs, data and services as REST APIs and lets COBOL programs call external APIs. Its documentation is at IBM z/OS Connect documentation; check the version your site runs, because the product has two documented lines.
-
Batch and files. Nightly extracts, as in the export program at the end of this page, publish the data without touching the programs.
-
Messaging and containers. For event-style integration the COBOL side publishes to a queue and the new services consume it; the patterns are in Messaging: Getting Started and Delivery Guarantees. New components are packaged and run as described in Docker.
-
Inside COBOL. Enterprise COBOL’s
JSON GENERATEandJSON PARSE(see JSON GENERATE and PARSE) produce and read JSON in the program itself, and Java interoperability (see Interoperability with C, Java and Python) lets a Java service call COBOL without OO COBOL.
The price of this option is that the interface now has two owners and the COBOL layout becomes a public contract:
adding a field to BOOKREC is a change to an API.
The strangler fig on a mainframe
The strangler fig replaces a system one capability at a time behind a routing layer, so that the old system shrinks until it can be switched off. The general technique, with its routing proxy, branch by abstraction, parallel run, data synchronisation and exit criteria, is explained on Migration Path: Legacy to Modern Stack and in Migration Overview. This page does not repeat it. It adds what is specific to COBOL:
-
The seam. Choose capabilities with a clear data boundary. For Circulation, "is this book available" (reads
BOOKMAST, no side effects) is a good first strangler; "post a loan" (updates three files and runs in the nightly chain) is a poor one. -
Anti-corruption layer. The facade translates the copybook model (fixed fields, status codes,
PIC 9flags) into the new domain model, so the new services never seeBOOK-STATUS = "3". -
Parallel run. Run the COBOL program and the replacement on the same input and compare outputs. Batch makes this easier than online work: the same
LOANTRANfile goes through both and the reports are diffed. Compare numbers after applying the rounding rules of the original (see Arithmetic and COMPUTE); a penny of difference is a defect. -
Data ownership. Only one side writes a given table at a time. The synchronisation techniques on the Backend page (change data capture, dual writes avoided) apply; on the mainframe side Db2 log-based replication and extract jobs play the part.
-
Exit. The COBOL program is retired only after its batch jobs, its reports, its audit trails and its year-end special cases have a replacement. The old system’s batch window is itself a behaviour to preserve or drop on purpose.
Translation and AI assistance: watsonx Code Assistant for Z
IBM watsonx Code Assistant for Z is IBM’s AI-assisted tool for mainframe application work. IBM’s product page describes these capabilities: automated discovery and analysis of applications and their dependencies, natural-language explanation of code, generation of COBOL through chat or inline suggestions, identifying the programs and data that belong in a modular service when refactoring COBOL and PL/I applications, source-level performance insights, and transformation of COBOL to Java with generated unit tests that compare the Java service with the original COBOL. The documentation set is at IBM watsonx Code Assistant for Z documentation. The documentation pages could not be read in full when this page was written, so no release number, feature matrix or supported-language list is given here; take those from IBM’s pages for the release you license.
Three cautions apply to any translation tool, this one included, and are conclusions about the technique, not claims about a product:
-
A translation is only as good as the proof of equivalence. Keep the COBOL as the oracle: run both versions on the same inputs (the parallel run above) and compare, including the numeric edge cases from USAGE and Numeric Representation (truncation, rounding, scaled decimals, invalid data).
-
Generated Java that mirrors COBOL paragraph by paragraph keeps the structure that made the program hard to change. Treat it as a first step, then refactor with the tests it gives you.
-
Review is not optional. Explanations and generated code can be wrong, and the reviewer has to know the original language; the skills in this guide are what make that review possible.
Taulli’s chapters on AI/ML, AIOps and RPA cover a broader field: machine learning models scoring data that sits on IBM Z, operational analytics that spot anomalies in system metrics, and robotic process automation or low-code tools that drive existing screens. They sit around the COBOL rather than in it; the generic tutorials are out of scope here. The practical consequence for a COBOL team is the same as for APIs: the more cleanly the data and the programs are exposed, the easier it is for any of those tools to use them.
Data migration concerns
Data outlives code. Most failed migrations fail on data, because the byte layout in a mainframe file is part of the program’s meaning. Check each of these before moving a single file.
| Concern | What goes wrong and what to do |
|---|---|
EBCDIC versus ASCII or UTF-8 |
Text fields are EBCDIC (code page 037 or a national variant such as 1047) on z/OS. Convert character fields with the right code page, and never apply a text conversion to a whole record: it corrupts packed-decimal and binary fields. Sort order changes too, see Legacy Features and Migration. |
Packed decimal ( |
These are bytes, not text. Unpack them with a program that knows the copybook, not with a generic file transfer. The sign nibble ( |
Zoned decimal sign |
A |
|
One storage area, several layouts: the record type decides how to read it. A converter needs the discriminator and a layout per type. See REDEFINES, RENAMES and TYPEDEF. |
|
The record length varies and the count field drives it. Read the count first. Variable records on z/OS carry a 4-byte record descriptor word, which a file transfer may keep or strip, so agree the format. |
Invalid data |
Fields that were never numeric (spaces in a |
Dates |
Two-digit years and special values ( |
VSAM and IMS structure |
A KSDS key becomes a primary key, an RRDS slot a row, an IMS hierarchy several related tables. See Indexed Files and VSAM and IMS DL/I Overview. |
Consistency |
Extract at a quiet point of the batch cycle, record counts and control totals on both sides, and reconcile. |
A fixed-layout export, with the layout visible
The most robust migration path is a COBOL program that reads the data with the real copybook and writes a neutral
format, here a comma-separated line. The program below builds one LOAN-MIG record in the layout discussed above (a
text key, a signed packed-decimal fine, a binary count and a variable table) into a 24-byte fixed record, writes it, reads
it back and prints the unpacked fields. A real export would read the existing file instead of building the record.
IDENTIFICATION DIVISION.
PROGRAM-ID. EXPMIG.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT LOANOUT ASSIGN TO "loanmig.dat"
ORGANIZATION IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD LOANOUT
RECORD CONTAINS 24 CHARACTERS.
01 LOAN-RAW PIC X(24).
WORKING-STORAGE SECTION.
01 LOAN-MIG.
05 LOAN-ID PIC X(6).
05 FINE-AMOUNT PIC S9(5)V99 COMP-3.
05 LINE-COUNT PIC 9(2) COMP.
05 LINE-ENTRY PIC X(4)
OCCURS 1 TO 3 TIMES
DEPENDING ON LINE-COUNT.
01 FINE-EDITED PIC -(5)9.99.
01 EOF-FLAG PIC X VALUE "N".
PROCEDURE DIVISION.
MAIN-PARA.
OPEN OUTPUT LOANOUT
MOVE "L00017" TO LOAN-ID
MOVE -12.50 TO FINE-AMOUNT
MOVE 2 TO LINE-COUNT
MOVE "B101" TO LINE-ENTRY (1)
MOVE "B202" TO LINE-ENTRY (2)
MOVE SPACES TO LOAN-RAW
MOVE LOAN-MIG TO LOAN-RAW
WRITE LOAN-RAW
CLOSE LOANOUT
OPEN INPUT LOANOUT
READ LOANOUT
AT END MOVE "Y" TO EOF-FLAG
END-READ
MOVE LOAN-RAW TO LOAN-MIG
MOVE FINE-AMOUNT TO FINE-EDITED
DISPLAY LOAN-ID "," FUNCTION TRIM(FINE-EDITED) ","
LINE-COUNT "," LINE-ENTRY (1) "," LINE-ENTRY (2)
CLOSE LOANOUT
STOP RUN.
Compiled with cobc -x -Wall -std=ibm expmig.cob (the ibm dialect gives COMP its IBM sizes, so a PIC 9(2) COMP item takes
2 bytes), no warnings, it prints:
L00017,-12.50,00002,B101,B202
The file holds 24 bytes. od -An -tx1 loanmig.dat shows them (the leading 4c is the ASCII letter L; on z/OS the same
field would be D3):
4c 30 30 30 31 37 00 01 25 0d 00 02 42 31 30 31
42 32 30 32 20 20 20 20
Read it field by field: six text bytes, then 00 01 25 0d, which is the packed-decimal value 1250 with the sign nibble
D (negative), scaled by the implied decimal point to -12.50. Then 00 02, the big-endian binary count, two four-byte
entries, and four spaces of padding, because the OCCURS DEPENDING ON group was 20 bytes long while the record is 24.
The record length is a property of the file format, not of the table. Note also that the display of a binary item
(00002) shows the digits its storage can hold; a PIC 9(2) COMP item is not limited to two digits at run time unless
the TRUNC option or -fbinary-truncate says so.
Source: Enterprise COBOL for z/OS 6.5 Language Reference: OCCURS clause; Language Reference: USAGE clause; GnuCOBOL 3.2 manual
For the text fields alone, an EBCDIC conversion with a standard tool is straightforward, which also shows why it must be
applied field by field (shell session, GNU iconv, the EBCDIC code page name is IBM037):
printf 'L00017' | iconv -f ASCII -t IBM037 | od -An -tx1
printf '\xd3\xf0\xf0\xf0\xf1\xf7' | iconv -f IBM037 -t UTF-8
printf '\x00\x01\x2c' | iconv -f IBM037 -t UTF-8 | od -An -tx1
d3 f0 f0 f0 f1 f7
L00017
00 01 c2 8c
The first two lines round-trip the key. The last one feeds the packed-decimal bytes 00 01 2c through the same
conversion and gets different bytes back: the 2c became the two UTF-8 bytes c2 8c. A file transfer that converts the
whole record would have damaged the amount in the same way. Transfer tools that convert only the character fields (given
the copybook), or an export program like the one above, avoid this.
Common mistakes
-
Starting with a rewrite. A rewrite of an unmeasured system tends to lose the rules nobody wrote down. Start with the inventory (programs, jobs, files, tables, interfaces) and the tests (a parallel run is the best test).
-
Converting a record as text. See the
iconvexample: packed-decimal and binary fields are bytes. -
Ignoring the batch window and the schedule. The scheduler, restart points and
GDGgenerations are behaviour. -
Treating translated code as finished. A translator moves the language; the design, the tests and the data model remain to be done.
-
Forgetting people and skills. The programs outlive the team that wrote them. Documentation and tests created for the migration are valuable even if the migration is later cancelled.