Data stores anti-pattern
VSAM alternate index coupling
Programs reach a KSDS through alternate index paths defined outside the code, in IDCAMS jobs and JCL, so access patterns, duplicate handling and index maintenance are invisible in the COBOL source.
- FAMILY
- Data stores
- CUTOVER RISK
- High
- Hides business logic or coupling that a rewrite will drop unless it is extracted explicitly.
- MODERN MAPPING
- Relational table with secondary index and explicit queries
- GENERATED ARTIFACT
- openapi.yaml
Before and after
legacy source → modern mapping
Legacy: exhibits the pattern
1 SELECT ACCT-MASTER ASSIGN TO ACCTMST2 ORGANIZATION IS INDEXED3 ACCESS MODE IS DYNAMIC4 RECORD KEY IS ACCT-NO5 ALTERNATE RECORD KEY IS ACCT-TAX-ID6 WITH DUPLICATES7 FILE STATUS IS WS-FS.8 ...9 MOVE IN-TAX-ID TO ACCT-TAX-ID10 START ACCT-MASTER KEY IS EQUAL TO ACCT-TAX-ID11 INVALID KEY SET WS-DONE TO TRUE12 END-START13 PERFORM UNTIL WS-DONE14 READ ACCT-MASTER NEXT RECORD15 AT END SET WS-DONE TO TRUE16 END-READ17 IF NOT WS-DONE18 IF ACCT-TAX-ID NOT = IN-TAX-ID19 SET WS-DONE TO TRUE20 ELSE21 ADD ACCT-BALANCE TO WS-EXPOSURE22 END-IF23 END-IF24 END-PERFORM.
Modern: Relational table with secondary index and explicit queries
1CREATE TABLE account (2 acct_no CHAR(10) PRIMARY KEY,3 tax_id CHAR(9) NOT NULL,4 balance DECIMAL(11,2) NOT NULL5);67-- was: AIX PROD.ACCTMST.TAXID.AIX (NONUNIQUEKEY)8CREATE INDEX ix_account_tax_id ON account (tax_id);910-- access pattern AP-07: total exposure by tax id11SELECT COALESCE(SUM(balance), 0) AS exposure12FROM account13WHERE tax_id = :taxId;
Why it is dangerous in modernization
A VSAM key-sequenced data set has one prime key. Every other way of finding a record goes through an alternate index: a separate KSDS built by IDCAMS DEFINE ALTERNATEINDEX, linked to the base cluster by a PATH, and kept current only if it is in the upgrade set. Programs declare ALTERNATE RECORD KEY in the SELECT clause and loop over duplicates with START and READ NEXT. The real query (all accounts for one taxpayer, all claims for one provider) is spread across a SELECT clause, a START, a READ NEXT loop that must notice when the key changes, an IDCAMS job, and a DD statement whose name is derived from the base DD name. A data migration that copies records and recreates the prime key loses every one of those access paths, and any program behavior that depended on the order of duplicates.
How PYD ENTERPRISES detects it
PYD ENTERPRISES parses IDCAMS control statements alongside COBOL and JCL. DEFINE ALTERNATEINDEX, RELATE, KEYS, UNIQUEKEY or NONUNIQUEKEY, UPGRADE and DEFINE PATH become catalog entities linked to the base cluster. In COBOL, the SELECT clause ties a file to its prime and alternate keys, and dataflow analysis follows START and READ NEXT loops to find the key comparison that ends each one. Each loop is exported as a named access pattern: base cluster, alternate key, predicate, termination condition and the paragraph that consumes each record. AIXs that are not in the upgrade set, yet are read by online programs, are flagged as potentially stale.
Maps to: Relational table with secondary index and explicit queries
Each alternate index becomes a secondary index on the target table, and each access pattern becomes a named query or repository method with an explicit ORDER BY. The order of duplicates, which VSAM decided implicitly, becomes a decision someone makes and writes down. Upgrade-set behavior disappears, because the database maintains indexes transactionally.
Generated specification fragment
1paths:2 /parties/{taxId}/exposure:3 get:4 operationId: getExposureByTaxId5 summary: Access pattern AP-07 (EXPOSURE.cbl)6 parameters:7 - name: taxId8 in: path9 required: true10 schema: { type: string, pattern: '^[0-9]{9}$' }11 responses:12 '200':13 content:14 application/json:15 schema:16 $ref: '#/components/schemas/Exposure'17 x-pyd-source: EXPOSURE.cbl:9-24
Every generated element links back to the source file and line range shown in the legacy pane. Review and sign off before building against it.
The definition lives in IDCAMS
The alternate index itself is defined in a utility job that may have run once, in the 1990s, and is kept only in a PDS member nobody opens. PYD ENTERPRISES reads those members as part of ingest.
1 DEFINE ALTERNATEINDEX -2 (NAME(PROD.ACCTMST.TAXID.AIX) -3 RELATE(PROD.ACCTMST.KSDS) -4 KEYS(9 40) -5 NONUNIQUEKEY -6 UPGRADE)7 DEFINE PATH -8 (NAME(PROD.ACCTMST.TAXID.PATH) -9 PATHENTRY(PROD.ACCTMST.TAXID.AIX))10 BLDINDEX INDATASET(PROD.ACCTMST.KSDS) -11 OUTDATASET(PROD.ACCTMST.TAXID.AIX)
What the loop really asks
The COBOL loop in EXPOSURE.cbl is a SUM over all accounts sharing a tax ID. Nothing in the source says SUM, and the termination test (ACCT-TAX-ID NOT = IN-TAX-ID) is the only thing that keeps the loop from summing the whole rest of the file in alternate key order. Forgetting that comparison is a classic defect in hand-written COBOL, and when the engine finds a START and READ NEXT loop with no key-change test, it reports it: the legacy program may be computing something nobody intended.
Coupling you only see at runtime
- In the JCL, the path is allocated on a DD whose name IBM COBOL derives from the base file's DD name with a sequence digit (ACCTMST1 for the first alternate key). Change one without the other and the program fails to open.
- An AIX defined without UPGRADE is not maintained when the base cluster changes; it is rebuilt by a nightly BLDINDEX. Online reads through it see yesterday's data.
- Several programs may share one path with different assumptions about duplicate order.
Each of these becomes a line item in the data migration plan, with the programs affected.
Related patterns
Usually found in the same codebase.
- Data storesCritical
IMS hierarchical navigation
Maps to Relational aggregate with foreign keys
- COBOLHigh
OCCURS DEPENDING ON
Maps to Bounded array (child collection)
- CICSCritical
CICS pseudo-conversational state
Maps to Stateless REST resource with explicit versioning
- JCLHigh
JCL condition code chains
Maps to Explicit step DAG with run conditions
Find every VSAM alternate index coupling in your codebase.
Run PYD ENTERPRISES in your private VPC and get each occurrence with file, line range, modern mapping and equivalence fixtures, ready for your architects to review.