Case Study 2: Copybook Versioning and Migration
Background
Pacific Northwest Savings and Loan has operated its core banking system for over two decades. The system processes checking accounts, savings accounts, certificates of deposit, and consumer loans through a network of thirty-eight COBOL batch programs and fifteen CICS online transactions. All programs share a single account record copybook, PNSL-ACCT-REC, that defines the 200-byte account master record.
In January 2026, the bank's compliance department announced a new regulatory requirement: every account record must now include a beneficial ownership indicator, a tax reporting classification code, and an enhanced Know Your Customer (KYC) verification date. These three new fields total 13 bytes. The current record layout has only 8 bytes of filler remaining. Adding 13 bytes means the record length must increase from 200 bytes to 205 bytes -- a breaking change that affects every program and every file in the system.
The migration cannot happen overnight. The bank processes transactions 24 hours a day, and a simultaneous recompilation of all fifty-three programs is operationally unacceptable. The development team must plan a phased migration where old and new versions of the copybook coexist, programs are migrated in waves, and backward compatibility is maintained throughout the transition period.
This case study follows the team through the design, implementation, and testing of this copybook migration.
Problem Statement
The existing copybook looks like this:
******************************************************************
* COPYBOOK: PNSL-ACCT-REC (Version 4.2)
* PURPOSE: Account master record for Pacific NW Savings & Loan
* RECORD LENGTH: 200 bytes
* PREFIX: AR- (design for COPY REPLACING)
******************************************************************
01 AR-ACCOUNT-RECORD.
05 AR-ACCT-NUMBER PIC X(12).
05 AR-CUST-ID PIC 9(10).
05 AR-ACCT-TYPE PIC X(02).
88 AR-CHECKING VALUE 'CK'.
88 AR-SAVINGS VALUE 'SV'.
88 AR-CERT-DEPOSIT VALUE 'CD'.
88 AR-CONSUMER-LOAN VALUE 'CL'.
05 AR-STATUS PIC X(01).
88 AR-OPEN VALUE 'O'.
88 AR-CLOSED VALUE 'C'.
88 AR-FROZEN VALUE 'F'.
88 AR-DORMANT VALUE 'D'.
05 AR-OPEN-DATE PIC 9(08).
05 AR-CLOSE-DATE PIC 9(08).
05 AR-CURRENT-BAL PIC S9(11)V99 COMP-3.
05 AR-AVAIL-BAL PIC S9(11)V99 COMP-3.
05 AR-INT-RATE PIC 9(02)V9(06) COMP-3.
05 AR-LAST-ACTIVITY PIC 9(08).
05 AR-BRANCH-CODE PIC X(04).
05 AR-OFFICER-ID PIC 9(06).
05 AR-PRODUCT-CODE PIC X(04).
05 AR-MONTHLY-FEE PIC S9(05)V99 COMP-3.
05 AR-OD-LIMIT PIC S9(09)V99 COMP-3.
05 AR-LAST-STMT-DATE PIC 9(08).
05 AR-YTD-INTEREST PIC S9(09)V99 COMP-3.
05 AR-YTD-FEES PIC S9(07)V99 COMP-3.
05 AR-MATURITY-DATE PIC 9(08).
05 AR-ORIGINATION-AMT PIC S9(11)V99 COMP-3.
05 AR-FILLER PIC X(08).
The new fields that must be added are:
| Field | PIC | Size | Purpose |
|---|---|---|---|
| AR-BENEF-OWNER-IND | X(01) | 1 byte | Beneficial ownership indicator (Y/N) |
| AR-TAX-CLASS-CODE | X(02) | 2 bytes | Tax reporting classification |
| AR-KYC-VERIFY-DATE | 9(08) | 8 bytes | KYC verification date (YYYYMMDD) |
| AR-KYC-STATUS | X(01) | 1 byte | KYC status (V=verified, P=pending, E=expired) |
| AR-CRS-COUNTRY | X(02) | 2 bytes | Common Reporting Standard country code |
Total new fields: 14 bytes. Available filler: 8 bytes. Net increase: 6 bytes, bringing the record from 200 to 206 bytes.
The team must answer three questions:
- How do we structure the new copybook version so that the record layout change is clean and maintainable?
- How do we allow old programs (still using the 200-byte layout) and new programs (using the 206-byte layout) to coexist during the migration period?
- How do we test that the migration does not corrupt data or break any of the fifty-three dependent programs?
Migration Strategy
Phase 1: Design the New Copybook Version
The team creates version 5.0 of the copybook with the new fields replacing the filler and extending the record:
******************************************************************
* COPYBOOK: PNSL-ACCT-REC (Version 5.0)
* PURPOSE: Account master record for Pacific NW Savings & Loan
* RECORD LENGTH: 206 bytes
* PREFIX: AR- (design for COPY REPLACING)
* CHANGE: Added regulatory compliance fields (CRS/KYC/BO)
* Record length increased from 200 to 206 bytes.
* Programs using V4.2 must be recompiled.
******************************************************************
01 AR-ACCOUNT-RECORD.
05 AR-ACCT-NUMBER PIC X(12).
05 AR-CUST-ID PIC 9(10).
05 AR-ACCT-TYPE PIC X(02).
88 AR-CHECKING VALUE 'CK'.
88 AR-SAVINGS VALUE 'SV'.
88 AR-CERT-DEPOSIT VALUE 'CD'.
88 AR-CONSUMER-LOAN VALUE 'CL'.
05 AR-STATUS PIC X(01).
88 AR-OPEN VALUE 'O'.
88 AR-CLOSED VALUE 'C'.
88 AR-FROZEN VALUE 'F'.
88 AR-DORMANT VALUE 'D'.
05 AR-OPEN-DATE PIC 9(08).
05 AR-CLOSE-DATE PIC 9(08).
05 AR-CURRENT-BAL PIC S9(11)V99 COMP-3.
05 AR-AVAIL-BAL PIC S9(11)V99 COMP-3.
05 AR-INT-RATE PIC 9(02)V9(06) COMP-3.
05 AR-LAST-ACTIVITY PIC 9(08).
05 AR-BRANCH-CODE PIC X(04).
05 AR-OFFICER-ID PIC 9(06).
05 AR-PRODUCT-CODE PIC X(04).
05 AR-MONTHLY-FEE PIC S9(05)V99 COMP-3.
05 AR-OD-LIMIT PIC S9(09)V99 COMP-3.
05 AR-LAST-STMT-DATE PIC 9(08).
05 AR-YTD-INTEREST PIC S9(09)V99 COMP-3.
05 AR-YTD-FEES PIC S9(07)V99 COMP-3.
05 AR-MATURITY-DATE PIC 9(08).
05 AR-ORIGINATION-AMT PIC S9(11)V99 COMP-3.
* --- V5.0 REGULATORY COMPLIANCE FIELDS ---
05 AR-BENEF-OWNER-IND PIC X(01).
88 AR-HAS-BENEF-OWNER VALUE 'Y'.
88 AR-NO-BENEF-OWNER VALUE 'N'.
05 AR-TAX-CLASS-CODE PIC X(02).
88 AR-TAX-INDIVIDUAL VALUE 'IN'.
88 AR-TAX-BUSINESS VALUE 'BZ'.
88 AR-TAX-EXEMPT VALUE 'EX'.
88 AR-TAX-FOREIGN VALUE 'FN'.
05 AR-KYC-VERIFY-DATE PIC 9(08).
05 AR-KYC-STATUS PIC X(01).
88 AR-KYC-VERIFIED VALUE 'V'.
88 AR-KYC-PENDING VALUE 'P'.
88 AR-KYC-EXPIRED VALUE 'E'.
05 AR-CRS-COUNTRY PIC X(02).
05 AR-FILLER PIC X(00).
The filler is now zero bytes. The team notes this in the header comment as a risk factor -- the next field addition will require another record length change.
Phase 2: Create a Compatibility Wrapper
During the transition period, some programs will be recompiled with the V5.0 copybook while others still run with the V4.2 layout. To handle this, the team creates a compatibility copybook that uses REPLACE to bridge the gap:
******************************************************************
* COPYBOOK: PNSL-ACCT-COMPAT
* PURPOSE: Compatibility wrapper for V4.2 to V5.0 migration.
* Programs compiled with this copybook can read both
* 200-byte (V4.2) and 206-byte (V5.0) records.
* USAGE: Include this instead of PNSL-ACCT-REC during
* the migration period.
******************************************************************
01 AR-ACCOUNT-RECORD.
05 AR-ACCT-NUMBER PIC X(12).
05 AR-CUST-ID PIC 9(10).
05 AR-ACCT-TYPE PIC X(02).
88 AR-CHECKING VALUE 'CK'.
88 AR-SAVINGS VALUE 'SV'.
88 AR-CERT-DEPOSIT VALUE 'CD'.
88 AR-CONSUMER-LOAN VALUE 'CL'.
05 AR-STATUS PIC X(01).
88 AR-OPEN VALUE 'O'.
88 AR-CLOSED VALUE 'C'.
88 AR-FROZEN VALUE 'F'.
88 AR-DORMANT VALUE 'D'.
05 AR-OPEN-DATE PIC 9(08).
05 AR-CLOSE-DATE PIC 9(08).
05 AR-CURRENT-BAL PIC S9(11)V99 COMP-3.
05 AR-AVAIL-BAL PIC S9(11)V99 COMP-3.
05 AR-INT-RATE PIC 9(02)V9(06) COMP-3.
05 AR-LAST-ACTIVITY PIC 9(08).
05 AR-BRANCH-CODE PIC X(04).
05 AR-OFFICER-ID PIC 9(06).
05 AR-PRODUCT-CODE PIC X(04).
05 AR-MONTHLY-FEE PIC S9(05)V99 COMP-3.
05 AR-OD-LIMIT PIC S9(09)V99 COMP-3.
05 AR-LAST-STMT-DATE PIC 9(08).
05 AR-YTD-INTEREST PIC S9(09)V99 COMP-3.
05 AR-YTD-FEES PIC S9(07)V99 COMP-3.
05 AR-MATURITY-DATE PIC 9(08).
05 AR-ORIGINATION-AMT PIC S9(11)V99 COMP-3.
* --- V5.0 EXTENSION (defaults for V4.2 records) ---
05 AR-V5-EXTENSION.
10 AR-BENEF-OWNER-IND PIC X(01).
88 AR-HAS-BENEF-OWNER VALUE 'Y'.
88 AR-NO-BENEF-OWNER VALUE 'N'.
10 AR-TAX-CLASS-CODE PIC X(02).
10 AR-KYC-VERIFY-DATE PIC 9(08).
10 AR-KYC-STATUS PIC X(01).
88 AR-KYC-VERIFIED VALUE 'V'.
88 AR-KYC-PENDING VALUE 'P'.
88 AR-KYC-EXPIRED VALUE 'E'.
10 AR-CRS-COUNTRY PIC X(02).
The new fields are grouped under AR-V5-EXTENSION, making it easy for migration programs to check whether the extension is populated.
Phase 3: Build the File Conversion Utility
The first program to migrate is a standalone utility that converts the 200-byte V4.2 file into the 206-byte V5.0 format. This utility reads old records, initializes the new fields with default values, and writes the expanded records:
IDENTIFICATION DIVISION.
PROGRAM-ID. PNLCONV5.
*================================================================*
* ACCOUNT FILE CONVERSION UTILITY - V4.2 TO V5.0 *
* Reads the 200-byte V4.2 account master and writes the *
* 206-byte V5.0 format with new regulatory fields initialized. *
*================================================================*
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OLD-MASTER
ASSIGN TO OLDMAST
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-OLD-STATUS.
SELECT NEW-MASTER
ASSIGN TO NEWMAST
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-NEW-STATUS.
SELECT CONVERT-REPORT
ASSIGN TO CNVRPT
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-RPT-STATUS.
DATA DIVISION.
FILE SECTION.
FD OLD-MASTER
RECORDING MODE IS F
RECORD CONTAINS 200 CHARACTERS.
01 OLD-ACCT-RECORD PIC X(200).
FD NEW-MASTER
RECORDING MODE IS F
RECORD CONTAINS 206 CHARACTERS.
01 NEW-ACCT-RECORD PIC X(206).
FD CONVERT-REPORT
RECORDING MODE IS F
RECORD CONTAINS 132 CHARACTERS.
01 RPT-LINE PIC X(132).
WORKING-STORAGE SECTION.
01 WS-FILE-STATUSES.
05 WS-OLD-STATUS PIC X(02).
05 WS-NEW-STATUS PIC X(02).
05 WS-RPT-STATUS PIC X(02).
01 WS-FLAGS.
05 WS-EOF PIC X VALUE 'N'.
88 END-OF-FILE VALUE 'Y'.
01 WS-COUNTERS.
05 WS-READ-COUNT PIC 9(09) VALUE 0.
05 WS-WRITE-COUNT PIC 9(09) VALUE 0.
05 WS-ERROR-COUNT PIC 9(07) VALUE 0.
* Old format (V4.2) - read into this structure
01 WS-OLD-RECORD.
05 WS-OLD-ACCT-NUMBER PIC X(12).
05 WS-OLD-CUST-ID PIC 9(10).
05 WS-OLD-ACCT-TYPE PIC X(02).
05 WS-OLD-STATUS PIC X(01).
05 WS-OLD-OPEN-DATE PIC 9(08).
05 WS-OLD-CLOSE-DATE PIC 9(08).
05 WS-OLD-CURRENT-BAL PIC S9(11)V99 COMP-3.
05 WS-OLD-AVAIL-BAL PIC S9(11)V99 COMP-3.
05 WS-OLD-INT-RATE PIC 9(02)V9(06) COMP-3.
05 WS-OLD-LAST-ACTIVITY PIC 9(08).
05 WS-OLD-BRANCH-CODE PIC X(04).
05 WS-OLD-OFFICER-ID PIC 9(06).
05 WS-OLD-PRODUCT-CODE PIC X(04).
05 WS-OLD-MONTHLY-FEE PIC S9(05)V99 COMP-3.
05 WS-OLD-OD-LIMIT PIC S9(09)V99 COMP-3.
05 WS-OLD-LAST-STMT-DATE PIC 9(08).
05 WS-OLD-YTD-INTEREST PIC S9(09)V99 COMP-3.
05 WS-OLD-YTD-FEES PIC S9(07)V99 COMP-3.
05 WS-OLD-MATURITY-DATE PIC 9(08).
05 WS-OLD-ORIGINATION-AMT PIC S9(11)V99 COMP-3.
05 WS-OLD-FILLER PIC X(08).
* New format (V5.0) - write from this structure
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==WS-NEW-==
==AR-ACCOUNT-RECORD== BY ==WS-NEW-RECORD==.
01 WS-RPT-DETAIL.
05 WS-RPT-ACCT-NUM PIC X(12).
05 FILLER PIC X(02) VALUE SPACES.
05 WS-RPT-CUST-ID PIC 9(10).
05 FILLER PIC X(02) VALUE SPACES.
05 WS-RPT-TYPE PIC X(02).
05 FILLER PIC X(02) VALUE SPACES.
05 WS-RPT-STATUS PIC X(10).
05 FILLER PIC X(02) VALUE SPACES.
05 WS-RPT-BALANCE PIC -(11)9.99.
05 FILLER PIC X(02) VALUE SPACES.
05 WS-RPT-RESULT PIC X(20).
01 WS-CURRENT-DATETIME.
05 WS-CURR-DATE.
10 WS-CURR-YEAR PIC 9(04).
10 WS-CURR-MONTH PIC 9(02).
10 WS-CURR-DAY PIC 9(02).
05 WS-CURR-TIME.
10 WS-CURR-HOUR PIC 9(02).
10 WS-CURR-MIN PIC 9(02).
10 WS-CURR-SEC PIC 9(02).
10 WS-CURR-HUND PIC 9(02).
05 WS-CURR-GMT-OFFSET PIC X(05).
PROCEDURE DIVISION.
0000-MAIN.
PERFORM 1000-INITIALIZE
PERFORM 2000-CONVERT-RECORDS
UNTIL END-OF-FILE
PERFORM 9000-FINALIZE
STOP RUN.
1000-INITIALIZE.
MOVE FUNCTION CURRENT-DATE
TO WS-CURRENT-DATETIME
OPEN INPUT OLD-MASTER
OUTPUT NEW-MASTER
CONVERT-REPORT
IF WS-OLD-STATUS NOT = '00'
DISPLAY 'ERROR OPENING OLD MASTER: '
WS-OLD-STATUS
STOP RUN
END-IF
STRING 'PNLCONV5 - ACCOUNT FILE CONVERSION'
DELIMITED BY SIZE
INTO RPT-LINE
END-STRING
WRITE RPT-LINE
MOVE SPACES TO RPT-LINE
STRING 'RUN DATE: ' WS-CURR-YEAR '/'
WS-CURR-MONTH '/' WS-CURR-DAY
' TIME: ' WS-CURR-HOUR ':'
WS-CURR-MIN ':' WS-CURR-SEC
DELIMITED BY SIZE
INTO RPT-LINE
END-STRING
WRITE RPT-LINE
MOVE ALL '-' TO RPT-LINE
WRITE RPT-LINE
PERFORM 1100-READ-OLD-MASTER.
1100-READ-OLD-MASTER.
READ OLD-MASTER INTO WS-OLD-RECORD
AT END SET END-OF-FILE TO TRUE
NOT AT END ADD 1 TO WS-READ-COUNT
END-READ.
2000-CONVERT-RECORDS.
* Move all existing fields from old to new layout
INITIALIZE WS-NEW-RECORD
MOVE WS-OLD-ACCT-NUMBER TO WS-NEW-ACCT-NUMBER
MOVE WS-OLD-CUST-ID TO WS-NEW-CUST-ID
MOVE WS-OLD-ACCT-TYPE TO WS-NEW-ACCT-TYPE
MOVE WS-OLD-STATUS TO WS-NEW-STATUS
MOVE WS-OLD-OPEN-DATE TO WS-NEW-OPEN-DATE
MOVE WS-OLD-CLOSE-DATE TO WS-NEW-CLOSE-DATE
MOVE WS-OLD-CURRENT-BAL TO WS-NEW-CURRENT-BAL
MOVE WS-OLD-AVAIL-BAL TO WS-NEW-AVAIL-BAL
MOVE WS-OLD-INT-RATE TO WS-NEW-INT-RATE
MOVE WS-OLD-LAST-ACTIVITY TO WS-NEW-LAST-ACTIVITY
MOVE WS-OLD-BRANCH-CODE TO WS-NEW-BRANCH-CODE
MOVE WS-OLD-OFFICER-ID TO WS-NEW-OFFICER-ID
MOVE WS-OLD-PRODUCT-CODE TO WS-NEW-PRODUCT-CODE
MOVE WS-OLD-MONTHLY-FEE TO WS-NEW-MONTHLY-FEE
MOVE WS-OLD-OD-LIMIT TO WS-NEW-OD-LIMIT
MOVE WS-OLD-LAST-STMT-DATE
TO WS-NEW-LAST-STMT-DATE
MOVE WS-OLD-YTD-INTEREST TO WS-NEW-YTD-INTEREST
MOVE WS-OLD-YTD-FEES TO WS-NEW-YTD-FEES
MOVE WS-OLD-MATURITY-DATE TO WS-NEW-MATURITY-DATE
MOVE WS-OLD-ORIGINATION-AMT
TO WS-NEW-ORIGINATION-AMT
* Initialize new V5.0 regulatory fields with defaults
MOVE 'N' TO WS-NEW-BENEF-OWNER-IND
MOVE SPACES TO WS-NEW-TAX-CLASS-CODE
MOVE ZEROES TO WS-NEW-KYC-VERIFY-DATE
MOVE 'P' TO WS-NEW-KYC-STATUS
MOVE SPACES TO WS-NEW-CRS-COUNTRY
* Special handling: derive tax class from account type
EVALUATE TRUE
WHEN WS-OLD-ACCT-TYPE = 'CK'
OR WS-OLD-ACCT-TYPE = 'SV'
OR WS-OLD-ACCT-TYPE = 'CD'
MOVE 'IN' TO WS-NEW-TAX-CLASS-CODE
WHEN WS-OLD-ACCT-TYPE = 'CL'
MOVE 'IN' TO WS-NEW-TAX-CLASS-CODE
END-EVALUATE
* Write converted record
WRITE NEW-ACCT-RECORD FROM WS-NEW-RECORD
ADD 1 TO WS-WRITE-COUNT
* Write report line
MOVE WS-NEW-ACCT-NUMBER TO WS-RPT-ACCT-NUM
MOVE WS-NEW-CUST-ID TO WS-RPT-CUST-ID
MOVE WS-NEW-ACCT-TYPE TO WS-RPT-TYPE
MOVE 'CONVERTED' TO WS-RPT-RESULT
MOVE WS-NEW-CURRENT-BAL TO WS-RPT-BALANCE
WRITE RPT-LINE FROM WS-RPT-DETAIL
PERFORM 1100-READ-OLD-MASTER.
9000-FINALIZE.
MOVE ALL '=' TO RPT-LINE
WRITE RPT-LINE
MOVE SPACES TO RPT-LINE
STRING 'RECORDS READ: '
DELIMITED BY SIZE
INTO RPT-LINE
END-STRING
WRITE RPT-LINE
DISPLAY 'PNLCONV5 CONVERSION COMPLETE'
DISPLAY ' RECORDS READ: ' WS-READ-COUNT
DISPLAY ' RECORDS WRITTEN: ' WS-WRITE-COUNT
DISPLAY ' ERRORS: ' WS-ERROR-COUNT
CLOSE OLD-MASTER
NEW-MASTER
CONVERT-REPORT.
Phase 4: REPLACE-Based Backward Compatibility
For programs that cannot be immediately recompiled with the V5.0 copybook, the team uses the REPLACE directive to temporarily mask the new fields. This technique allows a program compiled with V5.0 to operate as if it were still using V4.2, ignoring the extension fields:
*================================================================*
* PROGRAM: PNLRPT42 - Legacy report program
* This program uses REPLACE to maintain V4.2 behavior while
* compiled with the V5.0 copybook. The new fields exist in
* the record but are not referenced by the program logic.
*================================================================*
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-VERSION-FLAG PIC X(04) VALUE 'V4.2'.
* Include V5.0 copybook but program only uses V4.2 fields
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==WS-==
==AR-ACCOUNT-RECORD== BY ==WS-ACCT-REC==.
* Use REPLACE to create an alias that masks the extension
REPLACE ==WS-V5-FIELDS-NOT-USED==
BY ==CONTINUE==.
PROCEDURE DIVISION.
1000-PROCESS-REPORT.
* This program only references V4.2 fields
* The V5.0 extension fields are present in the record
* but are never referenced -- they pass through unchanged
DISPLAY 'Account: ' WS-ACCT-NUMBER
DISPLAY 'Balance: ' WS-CURRENT-BAL
DISPLAY 'Status: ' WS-STATUS
* No reference to WS-BENEF-OWNER-IND,
* WS-TAX-CLASS-CODE, WS-KYC-VERIFY-DATE, etc.
WS-V5-FIELDS-NOT-USED.
The key insight is that a program does not need to reference every field in a copybook. As long as the record length is correctly declared in the FD entry and the RECORD CONTAINS clause matches the actual file, the program can read and write 206-byte records while only accessing the first 200 bytes of each record. The new fields pass through untouched.
Phase 5: Phased Program Migration
The team categorizes all fifty-three programs into three migration waves:
Wave 1 (Week 1-2): Critical path programs -- The file conversion utility and the six programs that must populate or validate the new regulatory fields.
Wave 2 (Week 3-4): High-frequency programs -- The twenty programs that process the account file daily. These are recompiled with V5.0 but do not yet use the new fields.
Wave 3 (Week 5-6): Remaining programs -- The twenty-seven programs that run weekly, monthly, or on-demand. These are the lowest risk and are migrated last.
Testing Strategy
Level 1: Copybook Compilation Test
The first test verifies that the new copybook compiles cleanly in every context where it is used. The team creates a test harness program that includes the copybook with every REPLACING pattern used across the fifty-three programs:
IDENTIFICATION DIVISION.
PROGRAM-ID. PNLTEST1.
*================================================================*
* COPYBOOK COMPILATION TEST HARNESS *
* Verifies that V5.0 copybook compiles with all REPLACING *
* patterns used across the application portfolio. *
*================================================================*
DATA DIVISION.
FILE SECTION.
* Simulate FD usage patterns
FD TEST-FILE-1
RECORD CONTAINS 206 CHARACTERS.
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==F1-==
==AR-ACCOUNT-RECORD== BY ==F1-RECORD==.
FD TEST-FILE-2
RECORD CONTAINS 206 CHARACTERS.
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==F2-==
==AR-ACCOUNT-RECORD== BY ==F2-RECORD==.
WORKING-STORAGE SECTION.
* Test all known REPLACING patterns from production programs
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==WS-==
==AR-ACCOUNT-RECORD== BY ==WS-ACCT-REC==.
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==CURR-==
==AR-ACCOUNT-RECORD== BY ==CURR-ACCT-REC==.
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==PREV-==
==AR-ACCOUNT-RECORD== BY ==PREV-ACCT-REC==.
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==HOLD-==
==AR-ACCOUNT-RECORD== BY ==HOLD-ACCT-REC==.
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==RPT-==
==AR-ACCOUNT-RECORD== BY ==RPT-ACCT-REC==.
LINKAGE SECTION.
COPY PNSL-ACCT-REC
REPLACING ==AR-== BY ==LK-==
==AR-ACCOUNT-RECORD== BY ==LK-ACCT-REC==.
PROCEDURE DIVISION USING LK-ACCT-REC.
0000-TEST-MAIN.
* Verify all field names resolve correctly
MOVE F1-ACCT-NUMBER TO WS-ACCT-NUMBER
MOVE WS-CURRENT-BAL TO CURR-CURRENT-BAL
MOVE CURR-STATUS TO PREV-STATUS
MOVE PREV-BENEF-OWNER-IND TO HOLD-BENEF-OWNER-IND
MOVE HOLD-KYC-STATUS TO RPT-KYC-STATUS
MOVE RPT-CRS-COUNTRY TO LK-CRS-COUNTRY
* Verify 88-level conditions work with all prefixes
IF WS-OPEN
CONTINUE
END-IF
IF CURR-CHECKING
CONTINUE
END-IF
IF PREV-KYC-VERIFIED
CONTINUE
END-IF
IF HOLD-HAS-BENEF-OWNER
CONTINUE
END-IF
DISPLAY 'ALL COMPILATION TESTS PASSED'
STOP RUN.
If this test harness compiles without errors, every REPLACING pattern in the portfolio is confirmed to work with the new copybook.
Level 2: Data Integrity Test
The second test verifies that file conversion preserves all existing data. The team writes a comparison program that reads the old and new files in parallel and compares every V4.2 field byte-for-byte:
IDENTIFICATION DIVISION.
PROGRAM-ID. PNLTEST2.
*================================================================*
* DATA INTEGRITY VERIFICATION *
* Compares V4.2 and V5.0 files field-by-field to verify *
* that conversion preserved all existing data. *
*================================================================*
DATA DIVISION.
FILE SECTION.
FD OLD-FILE RECORD CONTAINS 200 CHARACTERS.
01 OLD-REC PIC X(200).
FD NEW-FILE RECORD CONTAINS 206 CHARACTERS.
01 NEW-REC PIC X(206).
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE 'N'.
88 ALL-DONE VALUE 'Y'.
01 WS-REC-NUM PIC 9(09) VALUE 0.
01 WS-ERR-COUNT PIC 9(07) VALUE 0.
01 WS-MATCH-COUNT PIC 9(09) VALUE 0.
* Overlay old record for field comparison
01 WS-OLD-OVERLAY.
05 WS-OLD-ACCT-NUM PIC X(12).
05 WS-OLD-REMAINDER PIC X(188).
* Overlay new record for field comparison
01 WS-NEW-OVERLAY.
05 WS-NEW-ACCT-NUM PIC X(12).
05 WS-NEW-REMAINDER PIC X(188).
05 WS-NEW-EXTENSION PIC X(06).
PROCEDURE DIVISION.
0000-MAIN.
OPEN INPUT OLD-FILE NEW-FILE
PERFORM UNTIL ALL-DONE
READ OLD-FILE INTO WS-OLD-OVERLAY
AT END SET ALL-DONE TO TRUE
END-READ
IF NOT ALL-DONE
READ NEW-FILE INTO WS-NEW-OVERLAY
ADD 1 TO WS-REC-NUM
IF WS-OLD-ACCT-NUM NOT = WS-NEW-ACCT-NUM
DISPLAY 'MISMATCH REC ' WS-REC-NUM
': OLD=' WS-OLD-ACCT-NUM
' NEW=' WS-NEW-ACCT-NUM
ADD 1 TO WS-ERR-COUNT
END-IF
IF WS-OLD-REMAINDER NOT = WS-NEW-REMAINDER
DISPLAY 'DATA DIFF REC ' WS-REC-NUM
' ACCT=' WS-OLD-ACCT-NUM
ADD 1 TO WS-ERR-COUNT
ELSE
ADD 1 TO WS-MATCH-COUNT
END-IF
END-IF
END-PERFORM
DISPLAY 'VERIFICATION COMPLETE'
DISPLAY ' RECORDS COMPARED: ' WS-REC-NUM
DISPLAY ' MATCHES: ' WS-MATCH-COUNT
DISPLAY ' MISMATCHES: ' WS-ERR-COUNT
IF WS-ERR-COUNT = 0
DISPLAY ' RESULT: ALL RECORDS MATCH'
ELSE
DISPLAY ' RESULT: *** ERRORS DETECTED ***'
END-IF
CLOSE OLD-FILE NEW-FILE
STOP RUN.
Level 3: Regression Testing
Every program in each migration wave undergoes full regression testing against a copy of the production data that has been converted to V5.0 format. The team maintains a test matrix:
| Program | Wave | Test Type | V4.2 Baseline | V5.0 Result | Match? |
|---|---|---|---|---|---|
| PNLPOST0 | 1 | Batch posting | Output hash | Output hash | Yes |
| PNLSTMT0 | 2 | Statement gen | Report checksum | Report checksum | Yes |
| PNLINT00 | 2 | Interest calc | Balance totals | Balance totals | Yes |
Each program's output under V5.0 must produce byte-identical results (for the V4.2 fields) compared to the V4.2 baseline. The new fields are verified separately by the Wave 1 programs that actually populate them.
Lessons Learned
Filler Strategy
The team learned the hard way that 8 bytes of filler was insufficient for a regulatory change. Their new standard mandates a minimum of 20% filler in every record copybook, providing a buffer for at least two minor version changes before a record length increase is needed.
The REPLACING Convention Matters
Because every program in the portfolio followed the same prefix-based REPLACING convention, the migration affected only the copybook and the FD RECORD CONTAINS clauses. If programs had used inconsistent conventions, each program would have required individual analysis and potentially unique REPLACING changes.
Coordinated Promotion
The conversion utility, the new copybook, and the Wave 1 programs must all be promoted to production simultaneously. The operations team used an Endevor package to group all components into a single, atomic promotion that either succeeds entirely or rolls back entirely.
Discussion Questions
-
The migration strategy uses a phased approach with three waves. What criteria would you use to determine which wave a program belongs to? What factors increase a program's migration risk?
-
The compatibility wrapper allows old programs to coexist with the new record format. What are the risks of this approach? What happens if a Wave 3 program writes a record and a Wave 1 program reads it -- are the new fields preserved?
-
The conversion utility initializes new fields with defaults (e.g., KYC status = 'P' for pending). What is the business impact of this default? How should the bank handle the backlog of accounts that need actual KYC verification?
-
The team consumed all remaining filler with this change. If another regulatory requirement arrives next quarter, what options are available? Compare the trade-offs of increasing the record length again versus redesigning the record with a variable-length extension area.
-
How would this migration differ if the account records were stored in a DB2 table instead of a sequential file? What advantages would ALTER TABLE ADD COLUMN provide compared to the copybook-driven approach?