Case Study 2: MedClaim Real-Time Eligibility Service
The Problem
Healthcare providers were frustrated. To verify a patient's insurance eligibility, office staff had to call MedClaim's phone center, wait on hold, and get a verbal confirmation. Alternatively, they could submit a batch eligibility file and wait until the next business day for results. Neither option worked well for a doctor's office that needed to know coverage status before a patient's appointment.
James Okafor was asked to build a real-time eligibility check API.
The Technical Challenge
The existing eligibility logic was embedded in a batch program (CLM-ELIG) that processed files of eligibility requests overnight. The program was 4,200 lines of COBOL with complex business rules covering:
- Plan type determination (HMO, PPO, POS, HDHP)
- Coverage date validation
- Dependent verification
- Pre-authorization requirements
- Network provider checks
- Deductible and out-of-pocket accumulator lookups
Rewriting this logic for an online program was estimated at 3 months with significant regression risk.
The Solution: Extract and Adapt
Sarah Kim, the business analyst, suggested a different approach: extract the core eligibility logic from CLM-ELIG into a reusable subprogram (ELIGCORE), then call that subprogram from both the batch program and a new CICS online program.
Step 1: Refactor the Batch Program
James extracted the eligibility determination logic from CLM-ELIG into ELIGCORE, a standalone subprogram with a clean LINKAGE SECTION interface:
LINKAGE SECTION.
01 LS-ELIG-REQUEST.
05 LS-MEMBER-ID PIC X(10).
05 LS-PROVIDER-ID PIC X(13).
05 LS-SERVICE-DATE PIC X(10).
05 LS-SERVICE-CODE PIC X(05).
05 LS-DIAGNOSIS-CODE PIC X(07).
01 LS-ELIG-RESPONSE.
05 LS-ELIGIBLE PIC X(01).
05 LS-PLAN-TYPE PIC X(03).
05 LS-COPAY PIC S9(05)V99 COMP-3.
05 LS-DEDUCT-REMAINING PIC S9(07)V99 COMP-3.
05 LS-OOP-REMAINING PIC S9(07)V99 COMP-3.
05 LS-COVERAGE-PCT PIC 9(03).
05 LS-STATUS-CODE PIC X(02).
05 LS-STATUS-MSG PIC X(50).
The batch program CLM-ELIG was modified to CALL ELIGCORE instead of executing the logic inline. Regression tests confirmed identical results for 100,000 test claims.
Step 2: Build the Online Wrapper
A new CICS program (ELIGCHK) was created as a thin wrapper around ELIGCORE:
- Receive COMMAREA from CICS
- Map COMMAREA fields to ELIGCORE's LINKAGE SECTION
- CALL ELIGCORE
- Map ELIGCORE's response back to the COMMAREA
- Return to CICS
The wrapper was 120 lines of COBOL — the business logic remained in ELIGCORE.
Step 3: Expose via z/OS Connect
The ELIGCHK program was exposed as a REST API:
POST /api/v1/eligibility/check
z/OS Connect handled the JSON-to-COMMAREA transformation.
Results
| Metric | Before | After |
|---|---|---|
| Response time | 24 hours (batch) or 8 min (phone) | 280ms |
| Daily capacity | 500K/month (batch) | 50,000/day real-time |
| Staff required | 12 phone agents | 0 (automated) |
| Provider satisfaction | 2.1/5 | 4.4/5 |
| Logic defects introduced | — | 0 (same ELIGCORE subprogram) |
Key Lessons
-
Refactoring before integration pays dividends. Extracting business logic into a callable subprogram enabled both batch and online access without duplicating code.
-
The riskiest part of modernization is rewriting business rules. By keeping ELIGCORE as the single source of eligibility logic, MedClaim avoided the regression risk that comes with reimplementation.
-
The wrapper pattern is powerful. ELIGCHK added no business logic — it was purely a translation layer between CICS COMMARETAs and the subprogram's LINKAGE SECTION.
-
Batch and online can coexist. The batch program still runs for large-volume eligibility files from clearinghouses. The real-time API handles point-of-service checks. Both use the same ELIGCORE.
Discussion Questions
- Why was extracting ELIGCORE into a subprogram preferable to duplicating the logic in a new online program?
- What testing strategy would you use to verify that the refactored batch program (calling ELIGCORE) produces identical results to the original?
- The response time is 280ms. How would you investigate if the requirement were 100ms?
- What happens if ELIGCORE needs a change (e.g., a new plan type)? How does the shared subprogram approach simplify this?