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:

  1. How do we structure the new copybook version so that the record layout change is clean and maintainable?
  2. 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?
  3. 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

  1. 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?

  2. 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?

  3. 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?

  4. 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.

  5. 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?