Case Study 2: MedClaim's Adjudication Engine Parameter Architecture
Background
MedClaim's claims adjudication engine processes 500,000 insurance claims per month. Each claim passes through six processing stages: eligibility verification, benefit determination, pricing, deductible/copay calculation, payment calculation, and audit trail writing. When James Okafor redesigned the engine in 2020, his central challenge was: how should data flow between these six tightly coupled stages?
"The old system passed 15 separate parameters between programs," James recalls. "The CALL statement wrapped across four lines. Adding a new field meant changing the CALL statement and the PROCEDURE DIVISION USING in every program. We once introduced a bug by adding a parameter in position 7 in the caller but position 8 in the callee. That cost us a week."
The Design Challenge
Each adjudication stage needs different data:
- Eligibility needs member information and service dates
- Benefits needs eligibility results plus plan information
- Pricing needs procedure codes and provider information
- Deductible needs pricing results plus member's year-to-date totals
- Payment needs all of the above
- Audit needs everything
With separate parameters, the later stages would require increasingly long parameter lists. And every stage's output becomes the next stage's input — a classic pipeline.
The Solution: Unified COMMAREA
James designed a single communication area (ADJUD-COMMAREA) that carries all data through the pipeline:
*================================================================
* COMARECP — MedClaim Adjudication COMMAREA
* Version: 3.2 — Last updated: 2024-01-15
*
* CHANGE HISTORY:
* v3.2: Added CA-TELEHEALTH-FLAG for virtual visit support
* v3.1: Added CA-PRIOR-AUTH fields
* v3.0: Complete redesign for ICD-11 support
*================================================================
01 ADJUD-COMMAREA.
* --- Control Section ---
05 CA-CONTROL.
10 CA-FUNCTION PIC X(4).
10 CA-STEP-NUMBER PIC 9(2).
10 CA-TIMESTAMP PIC X(26).
10 CA-USER-ID PIC X(8).
10 CA-BATCH-ID PIC X(12).
10 CA-TRACE-LEVEL PIC 9.
88 CA-NO-TRACE VALUE 0.
88 CA-TRACE-ERROR VALUE 1.
88 CA-TRACE-ALL VALUE 9.
* --- Claim Input Section ---
05 CA-CLAIM-INPUT.
10 CA-CLAIM-ID PIC X(15).
10 CA-MEMBER-ID PIC X(12).
10 CA-PROVIDER-ID PIC X(10).
10 CA-FACILITY-ID PIC X(10).
10 CA-SERVICE-DATE PIC 9(8).
10 CA-SUBMIT-DATE PIC 9(8).
10 CA-TELEHEALTH-FLAG PIC X.
88 CA-TELEHEALTH VALUE 'Y'.
10 CA-PRIOR-AUTH-NUM PIC X(15).
* --- Diagnosis Codes (up to 12) ---
05 CA-DIAGNOSES.
10 CA-DIAG-COUNT PIC 9(2).
10 CA-DIAG-ENTRY OCCURS 12 TIMES.
15 CA-DIAG-CODE PIC X(8).
15 CA-DIAG-DESC PIC X(40).
15 CA-DIAG-TYPE PIC X.
* --- Procedure Lines (up to 25) ---
05 CA-PROCEDURES.
10 CA-PROC-COUNT PIC 9(2).
10 CA-PROC-LINE OCCURS 25 TIMES.
15 CA-PROC-CODE PIC X(5).
15 CA-PROC-MOD PIC X(2) OCCURS 4.
15 CA-PROC-UNITS PIC 9(3).
15 CA-CHARGE-AMT PIC S9(7)V99 COMP-3.
15 CA-ALLOWED-AMT PIC S9(7)V99 COMP-3.
15 CA-PAID-AMT PIC S9(7)V99 COMP-3.
15 CA-LINE-STATUS PIC X(2).
* --- Eligibility Results (set by ADJELIG) ---
05 CA-ELIG-RESULTS.
10 CA-ELIG-STATUS PIC X(2).
88 CA-ELIG-ACTIVE VALUE 'AC'.
88 CA-ELIG-TERMED VALUE 'TR'.
88 CA-ELIG-COBRA VALUE 'CB'.
10 CA-PLAN-ID PIC X(10).
10 CA-GROUP-ID PIC X(10).
10 CA-EFF-DATE PIC 9(8).
10 CA-TERM-DATE PIC 9(8).
* --- Benefit Results (set by ADJBNFT) ---
05 CA-BENEFIT-RESULTS.
10 CA-COVERED-FLAG PIC X.
10 CA-BENEFIT-PCT PIC 9(3).
10 CA-COPAY-TYPE PIC X.
10 CA-COPAY-FLAT PIC S9(5)V99 COMP-3.
10 CA-DEDUCT-APPLIES PIC X.
10 CA-MAX-BENEFIT PIC S9(7)V99 COMP-3.
* --- Financial Results (set by ADJDEDC/ADJPAY) ---
05 CA-FINANCIAL-RESULTS.
10 CA-TOTAL-CHARGES PIC S9(9)V99 COMP-3.
10 CA-TOTAL-ALLOWED PIC S9(9)V99 COMP-3.
10 CA-TOTAL-DEDUCT PIC S9(7)V99 COMP-3.
10 CA-TOTAL-COPAY PIC S9(7)V99 COMP-3.
10 CA-TOTAL-COINS PIC S9(7)V99 COMP-3.
10 CA-TOTAL-PAID PIC S9(9)V99 COMP-3.
10 CA-MEMBER-RESP PIC S9(9)V99 COMP-3.
* --- Error Section ---
05 CA-ERROR-INFO.
10 CA-RETURN-CODE PIC S9(4) COMP.
88 CA-SUCCESS VALUE 0.
88 CA-WARNING VALUE 4.
88 CA-ERROR VALUE 8.
88 CA-SEVERE VALUE 12.
10 CA-ERROR-COUNT PIC 9(2).
10 CA-ERRORS.
15 CA-ERR-ENTRY OCCURS 10 TIMES.
20 CA-ERR-STEP PIC 9(2).
20 CA-ERR-CODE PIC X(8).
20 CA-ERR-MSG PIC X(50).
20 CA-ERR-FIELD PIC X(20).
Key Design Decisions
Decision 1: BY REFERENCE for the COMMAREA
Since all stages need to both read and modify the COMMAREA, it is always passed BY REFERENCE:
CALL 'ADJELIG' USING BY REFERENCE ADJUD-COMMAREA
James considered passing some sections BY CONTENT to protect them, but rejected it: "The copy overhead for a structure this size — about 3KB — multiplied by 500,000 claims is significant. And every stage needs to write its results into the structure. BY REFERENCE is the right choice here."
Decision 2: Accumulating Errors
Rather than stopping at the first error, the COMMAREA accumulates up to 10 errors. This allows the system to report all validation failures in a single pass:
ADD-ERROR.
IF CA-ERROR-COUNT < 10
ADD 1 TO CA-ERROR-COUNT
MOVE CA-STEP-NUMBER TO
CA-ERR-STEP(CA-ERROR-COUNT)
MOVE WS-ERR-CODE TO
CA-ERR-CODE(CA-ERROR-COUNT)
MOVE WS-ERR-MSG TO
CA-ERR-MSG(CA-ERROR-COUNT)
END-IF
* Set return code to highest severity
IF WS-ERR-SEVERITY > CA-RETURN-CODE
MOVE WS-ERR-SEVERITY TO CA-RETURN-CODE
END-IF.
Decision 3: Version Control via FILLER
To support backward compatibility when the COMMAREA grows, James reserved space at the end:
* --- Reserved for future use ---
05 CA-RESERVED PIC X(200).
When new fields are needed, they are added by reducing CA-RESERVED and defining new fields before it. Existing compiled programs that pass the full COMMAREA continue to work because the overall structure size does not change.
Results
| Metric | 15-Parameter Design | COMMAREA Design |
|---|---|---|
| CALL statement complexity | 4-5 lines per CALL | 1 line per CALL |
| Risk of parameter order bugs | High | Eliminated |
| Adding a new data field | Change 12 programs | Change copybook only |
| Error reporting | First error only | Up to 10 errors |
| Cross-stage data access | Complex chaining | Direct field access |
Sarah Kim observed the business impact: "When we needed to add telehealth support during the 2020 pandemic, we added CA-TELEHEALTH-FLAG to the COMMAREA, modified ADJBNFT to check it, and deployed in three days. Under the old architecture, that would have been a three-week project touching six programs."
Limitations Encountered
-
Structure size: At 3KB, the COMMAREA is not small. In CICS, where COMMAREAs are limited (typically 32KB max, but best practice is under 4KB), this is close to the limit.
-
Every program sees everything: The pricing module can read and modify eligibility results, even though it should not need to. Discipline replaces enforcement.
-
Binary compatibility: Recompiling only some programs after a copybook change can cause alignment issues if COMP fields shift position.
Discussion Questions
-
James rejected BY CONTENT for performance reasons. At what COMMAREA size would the copy overhead become negligible compared to other processing costs? How would you measure this?
-
The reserved space pattern (CA-RESERVED) provides forward compatibility. What happens when the reserved space runs out? How would you handle a major restructuring?
-
Each subprogram has access to the entire COMMAREA, including sections it should not modify. How would you enforce access discipline without compiler support?
-
The error accumulation pattern stops at 10 errors. What should the system do if more than 10 errors occur? Is there a better approach?
-
If you were redesigning this system today, would you still use a single COMMAREA, or would you split it into smaller, stage-specific structures? What factors would influence your decision?