Case Study 2: Pinnacle Health's Claims Status Notification System


Background

Pinnacle Health Insurance processes 50 million claims per month through a COBOL-based adjudication engine running on z/OS. The engine is a masterpiece of batch processing: claims arrive as EDI 837 files, are parsed into DB2 staging tables, adjudicated by a rule engine (2,800 COBOL programs organized in a 47-step job stream), and results are transmitted back as EDI 835 remittance files.

The problem wasn't the adjudication. The problem was that nobody knew what was happening while it happened.

Members called the customer service line to ask "Where is my claim?" and the representatives had no real-time answer. The claims status inquiry screen showed the last completed batch status — updated once per night. A claim submitted Monday morning would show "RECEIVED" until Tuesday morning's batch completed, at which point it might jump to "ADJUDICATED — APPROVED." No intermediate visibility. No proactive notification.

Ahmad Rashidi had been pushing for real-time claims status notifications for two years. "Every Amazon package has real-time tracking," he said during the 2023 planning meeting. "Our members can't get real-time tracking on a $47,000 hospital claim. That's not a technology problem. That's a priority problem."

Diane Okoye was assigned to solve it. Her constraint: the adjudication engine could not be modified. It was in the middle of a HIPAA 5010-to-6020 EDI format migration, and the compliance team had frozen all non-compliance code changes for 18 months.


Requirements

  1. Real-time status events for every claim as it progresses through adjudication (received, validated, assigned, in review, adjudicated, payment issued, EOB sent)
  2. Multi-channel notification — email, SMS, and mobile app push notifications to members
  3. Provider portal updates — real-time status visible to healthcare providers
  4. Customer service dashboard — representatives see real-time status without calling the batch team
  5. No modifications to the adjudication engine — all instrumentation must be non-invasive
  6. HIPAA compliance — all events containing PHI (Protected Health Information) must be encrypted, logged, and access-controlled

Architecture Design

Event Capture Strategy

Diane's first challenge: how to capture claim status changes from an engine she couldn't modify. She identified seven points in the adjudication flow where the claim status changes:

Status Transition CICS Program CICS Command File/Resource
RECEIVED CLMRECV1 WRITE FILE CLMSTAGE
VALIDATED CLMVAL01 REWRITE FILE CLMSTAGE
ASSIGNED CLMASSN1 WRITE FILE CLMASSIGN
IN_REVIEW CLMRVW01 START TRANSID — (transaction start)
ADJUDICATED CLMADJ01 REWRITE FILE CLMRESULT
PAYMENT_ISSUED PAYMNT01 WRITE FILE CLMPAYMT
EOB_SENT EOBGEN01 WRITE FILE CLMEOB

Each transition could be captured by a CICS event binding targeting the specific CICS command.

CICS Event Binding Implementation

Diane created seven event bindings — one per status transition. Here's the binding for the ADJUDICATED transition (the most critical for member notifications):

<event-binding name="ClaimAdjudicated">
  <capture-specification>
    <event-capture name="AdjCapture"
                   component="CLMADJ01"
                   capture-point="FILE_REWRITE"
                   current-context="CLMRESULT">
      <filter>
        <condition field-offset="0"
                   field-length="2"
                   operator="NE"
                   value="  "/>
      </filter>
      <capture-data>
        <data-item name="ClaimNumber"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="0"
                   length="15"/>
        <data-item name="MemberID"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="15"
                   length="12"/>
        <data-item name="ProviderID"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="27"
                   length="10"/>
        <data-item name="AdjResult"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="37"
                   length="8"/>
        <data-item name="BilledAmount"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="45"
                   length="8"/>
        <data-item name="AllowedAmount"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="53"
                   length="8"/>
        <data-item name="PaidAmount"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="61"
                   length="8"/>
        <data-item name="ReasonCode1"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="69"
                   length="5"/>
        <data-item name="ReasonCode2"
                   source="CONTAINER"
                   container-name="CLM-DATA"
                   offset="74"
                   length="5"/>
      </capture-data>
    </event-capture>
  </capture-specification>

  <event-emission>
    <adapter-name>MQAdapter</adapter-name>
    <adapter-properties>
      <property name="queue-manager" value="PHQM01"/>
      <property name="topic-string"
                value="PH/CLAIMS/STATUS/ADJUDICATED"/>
      <property name="format" value="JSON"/>
      <property name="persistence" value="PERSISTENT"/>
    </adapter-properties>
  </event-emission>
</event-binding>

Topic Hierarchy

PH/
  CLAIMS/
    STATUS/
      RECEIVED           ← claim entered the system
      VALIDATED           ← data validation passed
      ASSIGNED            ← assigned to adjudicator
      IN_REVIEW           ← adjudication in progress
      ADJUDICATED         ← adjudication complete (approve/deny/pend)
      PAYMENT_ISSUED      ← payment generated
      EOB_SENT            ← explanation of benefits delivered

Subscriber Architecture

PH/CLAIMS/STATUS/#  (all status events)
  |
  +---> NOTIFY.MEMBER.INBOUND
  |       → MemberNotify program (triggered)
  |       → Sends email/SMS/push based on member preferences
  |
  +---> NOTIFY.PROVIDER.INBOUND
  |       → ProviderPortal projection program (triggered)
  |       → Updates provider-facing status DB2 table
  |
  +---> CSR.DASHBOARD.INBOUND
  |       → CSR Dashboard projection program (triggered)
  |       → Updates customer service rep real-time view
  |
  +---> AUDIT.CLAIMS.INBOUND
  |       → ClaimsAudit program (triggered)
  |       → HIPAA audit trail — every status change logged
  |
  +---> ANALYTICS.CLAIMS.INBOUND
          → ClaimsAnalytics program (long-running consumer)
          → Processing time analytics, bottleneck detection

Member Notification Program (MBRNOTFY)

The member notification program is the consumer that members actually see. It's an MQ-triggered CICS transaction that:

  1. Retrieves the trigger message and opens the subscription queue
  2. Reads each claim status event
  3. Looks up the member's notification preferences in DB2 (email, SMS, push, or any combination)
  4. Formats channel-appropriate notification messages
  5. Queues notifications for delivery: - Email: writes to the email gateway queue (MQ) - SMS: writes to the SMS gateway queue (MQ) - Push: writes to the mobile push notification API queue (MQ to z/OS Connect)
  6. Logs the notification attempt for HIPAA audit

The notification formatting is claim-status-specific. An ADJUDICATED notification includes the result, the allowed amount, and the member's responsibility. A RECEIVED notification is simpler: confirmation that the claim was received with an estimated processing time.

       3000-FORMAT-NOTIFICATION.
           EVALUATE WS-CLAIM-STATUS
               WHEN 'RECEIVED'
                   STRING
                       'Your claim ' DELIMITED SIZE
                       WS-CLAIM-NUMBER DELIMITED SPACES
                       ' has been received. '
                       'Estimated processing time: '
                       WS-EST-DAYS DELIMITED SIZE
                       ' business days.'
                       DELIMITED SIZE
                   INTO WS-NOTIFY-TEXT
                   END-STRING

               WHEN 'ADJUDICATED'
                   EVALUATE WS-ADJ-RESULT
                       WHEN 'APPROVED'
                           STRING
                               'Your claim '
                               DELIMITED SIZE
                               WS-CLAIM-NUMBER
                               DELIMITED SPACES
                               ' has been approved. '
                               'Billed: $'
                               WS-BILLED-FMT
                               DELIMITED SPACES
                               ' Allowed: $'
                               WS-ALLOWED-FMT
                               DELIMITED SPACES
                               ' Your responsibility: $'
                               WS-MEMBER-RESP-FMT
                               DELIMITED SPACES
                               '.'
                               DELIMITED SIZE
                           INTO WS-NOTIFY-TEXT
                           END-STRING
                       WHEN 'DENIED'
                           STRING
                               'Your claim '
                               DELIMITED SIZE
                               WS-CLAIM-NUMBER
                               DELIMITED SPACES
                               ' was not approved. Reason: '
                               WS-DENIAL-REASON-TEXT
                               DELIMITED SPACES
                               '. You may file an appeal '
                               'within 180 days.'
                               DELIMITED SIZE
                           INTO WS-NOTIFY-TEXT
                           END-STRING
                   END-EVALUATE

               WHEN 'PAYMENT_ISSUED'
                   STRING
                       'Payment of $'
                       DELIMITED SIZE
                       WS-PAID-FMT DELIMITED SPACES
                       ' has been issued for claim '
                       WS-CLAIM-NUMBER DELIMITED SPACES
                       '. Check or EFT will arrive in '
                       '5-7 business days.'
                       DELIMITED SIZE
                   INTO WS-NOTIFY-TEXT
                   END-STRING
           END-EVALUATE.

HIPAA Compliance Architecture

Ahmad Rashidi's compliance requirements shaped several architectural decisions:

Event encryption. All events containing PHI (member ID, claim amounts, diagnosis codes) are encrypted using z/OS ICSF before being placed on MQ topics. The MQ channels use TLS 1.2 for in-flight encryption. Subscription queues have RACF profiles restricting GET access to authorized programs only.

Audit trail. Every event emission, every notification delivery, and every status inquiry is logged to a dedicated audit DB2 table. The audit subscriber receives every event and creates an immutable record. Audit log access requires a separate RACF authorization class.

Minimum necessary principle. Different subscribers receive different levels of detail. The analytics subscriber receives claim counts and processing times but not member IDs or amounts. The member notification subscriber receives the member's own data. The provider subscriber receives only data relevant to that provider. This is implemented through multiple topic subscriptions with content filtering at the consumer level.

-- HIPAA audit trail table
CREATE TABLE PH_CLAIMS_EVENT_AUDIT (
    AUDIT_SEQ           INTEGER GENERATED ALWAYS AS IDENTITY,
    EVENT_ID            CHAR(36) NOT NULL,
    EVENT_TYPE          VARCHAR(30) NOT NULL,
    EVENT_TIMESTAMP     TIMESTAMP NOT NULL,
    CLAIM_NUMBER        CHAR(15) NOT NULL,
    MEMBER_ID           CHAR(12) NOT NULL,
    STATUS_FROM         VARCHAR(20),
    STATUS_TO           VARCHAR(20) NOT NULL,
    EMITTED_BY          CHAR(8),
    RECEIVED_BY         CHAR(8),
    NOTIFICATION_SENT   CHAR(1) DEFAULT 'N',
    NOTIFICATION_CHANNEL VARCHAR(10),
    AUDIT_TIMESTAMP     TIMESTAMP DEFAULT CURRENT TIMESTAMP,
    PRIMARY KEY (AUDIT_SEQ)
);

CREATE INDEX IX_CLAIMS_AUDIT_CLAIM
    ON PH_CLAIMS_EVENT_AUDIT (CLAIM_NUMBER, EVENT_TIMESTAMP);

CREATE INDEX IX_CLAIMS_AUDIT_MEMBER
    ON PH_CLAIMS_EVENT_AUDIT (MEMBER_ID, EVENT_TIMESTAMP);

CQRS Implementation — Claims Status Read Model

The claims adjudication engine stores claim data across 14 normalized DB2 tables. A status inquiry requires joining 7 of them — a 400ms query that was acceptable for batch reporting but unacceptable for real-time customer service.

Diane implemented CQRS: a denormalized "claims status" read table maintained by an event-driven projection program.

-- Denormalized read model for claims status
CREATE TABLE PH_CLAIMS_STATUS_VIEW (
    CLAIM_NUMBER        CHAR(15) NOT NULL,
    MEMBER_ID           CHAR(12) NOT NULL,
    PROVIDER_ID         CHAR(10),
    CURRENT_STATUS      VARCHAR(20) NOT NULL,
    STATUS_TIMESTAMP    TIMESTAMP NOT NULL,
    DATE_RECEIVED       DATE,
    DATE_VALIDATED      DATE,
    DATE_ASSIGNED       DATE,
    DATE_IN_REVIEW      DATE,
    DATE_ADJUDICATED    DATE,
    ADJ_RESULT          CHAR(8),
    BILLED_AMOUNT       DECIMAL(11,2),
    ALLOWED_AMOUNT      DECIMAL(11,2),
    PAID_AMOUNT         DECIMAL(11,2),
    MEMBER_RESP         DECIMAL(11,2),
    REASON_CODE_1       CHAR(5),
    REASON_CODE_2       CHAR(5),
    DATE_PAYMENT_ISSUED DATE,
    PAYMENT_METHOD      CHAR(3),
    DATE_EOB_SENT       DATE,
    LAST_UPDATE_TS      TIMESTAMP DEFAULT CURRENT TIMESTAMP,
    PRIMARY KEY (CLAIM_NUMBER)
);

CREATE INDEX IX_STATUS_MEMBER
    ON PH_CLAIMS_STATUS_VIEW (MEMBER_ID, CURRENT_STATUS);

The projection program subscribes to PH/CLAIMS/STATUS/# and updates the denormalized table for each event:

       4000-UPDATE-STATUS-VIEW.
           EVALUATE WS-CLAIM-STATUS
               WHEN 'RECEIVED'
                   EXEC SQL
                       INSERT INTO PH_CLAIMS_STATUS_VIEW
                           (CLAIM_NUMBER, MEMBER_ID,
                            PROVIDER_ID, CURRENT_STATUS,
                            STATUS_TIMESTAMP, DATE_RECEIVED)
                       VALUES
                           (:WS-CLAIM-NUMBER, :WS-MEMBER-ID,
                            :WS-PROVIDER-ID, 'RECEIVED',
                            :WS-EVENT-TIMESTAMP,
                            CURRENT DATE)
                   END-EXEC
               WHEN 'ADJUDICATED'
                   EXEC SQL
                       UPDATE PH_CLAIMS_STATUS_VIEW
                       SET CURRENT_STATUS = 'ADJUDICATED',
                           STATUS_TIMESTAMP = :WS-EVENT-TS,
                           DATE_ADJUDICATED = CURRENT DATE,
                           ADJ_RESULT = :WS-ADJ-RESULT,
                           BILLED_AMOUNT = :WS-BILLED-AMT,
                           ALLOWED_AMOUNT = :WS-ALLOWED-AMT,
                           PAID_AMOUNT = :WS-PAID-AMT,
                           MEMBER_RESP = :WS-MEMBER-RESP,
                           REASON_CODE_1 = :WS-REASON-1,
                           REASON_CODE_2 = :WS-REASON-2,
                           LAST_UPDATE_TS =
                               CURRENT TIMESTAMP
                       WHERE CLAIM_NUMBER =
                               :WS-CLAIM-NUMBER
                   END-EXEC
               WHEN 'PAYMENT_ISSUED'
                   EXEC SQL
                       UPDATE PH_CLAIMS_STATUS_VIEW
                       SET CURRENT_STATUS = 'PAYMENT_ISSUED',
                           STATUS_TIMESTAMP = :WS-EVENT-TS,
                           DATE_PAYMENT_ISSUED = CURRENT DATE,
                           PAYMENT_METHOD = :WS-PAY-METHOD,
                           LAST_UPDATE_TS =
                               CURRENT TIMESTAMP
                       WHERE CLAIM_NUMBER =
                               :WS-CLAIM-NUMBER
                   END-EXEC
           END-EVALUATE.

Query performance improvement:

Query Before (7-table join) After (single table)
Single claim status 400ms 2ms
Member's last 10 claims 1,200ms 8ms
Provider's pending claims 3,500ms 45ms

The customer service representatives now see real-time claim status in under 10 milliseconds. The "Where is my claim?" call volume dropped 62% in the first quarter after deployment.


Operational Model

Monitoring

Diane's team monitors five key metrics:

  1. Event emission rate — events emitted per minute by each event binding. A sudden drop indicates the adjudication engine has stopped or the event binding has been disabled.

  2. Subscription queue depths — all five subscription queues are monitored with alerts at 5,000 messages. The analytics queue tolerates higher depths (batch consumer), but the notification and dashboard queues should be near-zero during business hours.

  3. Notification delivery rate — successful notifications per minute. Compared against event emission rate to detect delivery failures.

  4. Projection lag — the time difference between the event timestamp and the status view's LAST_UPDATE_TS. Should be under 5 seconds during normal operation.

  5. DLQ depth — any message on the dead letter queue triggers an immediate alert. In a healthcare system, a failed event could mean a member doesn't receive a critical notification about their claim.

Failure Scenarios

Failure Impact Recovery
EP adapter can't reach MQ Events stop emitting; adjudication continues unaffected Fix MQ connectivity; events published since last batch checkpoint are re-captured by replaying the checkpoint
Notification program abends Notifications stop; events accumulate on subscription queue Fix abend cause; restart triggered program; accumulated events are processed automatically
Status view projection fails Dashboard shows stale data Fix projection; replay events from subscription queue; if queue was drained, replay from audit log
MQ queue manager restart Durable subscriptions survive; non-persistent messages lost Restart completes; triggered programs restart automatically; persistent messages are delivered

Results After 12 Months

Metric Before After
"Where is my claim?" call volume 23,000/month 8,700/month (62% reduction)
Customer satisfaction (claim tracking) 34% satisfied 78% satisfied
Average time to answer status inquiry 4.2 minutes (manual lookup) Instant (dashboard)
Event bindings deployed 0 7
Subscriber applications 0 5
Daily events processed 0 3.2 million
Adjudication engine code changes Zero

The most significant outcome wasn't technical — it was cultural. "For the first time, the claims team sees what their system does in real time," Diane says. "They used to wait for the nightly batch report to know if something was wrong. Now they have a dashboard that shows claim flow minute by minute. They've caught three processing bottlenecks that had been invisible for years."

Ahmad Rashidi adds the compliance perspective: "The HIPAA audit trail is a byproduct. We get a complete, immutable, timestamped record of every claim status change as it happens. Our auditors used to reconstruct timelines from batch log files. Now they query a table. The regulatory exam went from three weeks of data gathering to three days."


Key Takeaways for Your Architecture

  1. CICS EP can instrument systems you can't modify. Pinnacle captured 7 event types from 7 programs without changing a single line of application code. When your adjudication engine is in a code freeze, EP is your backdoor to observability.

  2. CQRS solves the read performance problem. The normalized write model (14 tables, 7-table joins) serves adjudication correctness. The denormalized read model (1 table) serves real-time status inquiries. Events bridge the two.

  3. Every subscriber queue needs monitoring. Pinnacle learned this early from CNB's experience and set up alerts before go-live. The analytics queue depth alert fired on day 3 (consumer batch job schedule was wrong). Caught and fixed before impact.

  4. Notification is a domain, not an afterthought. The member notification program handles formatting, channel selection, preference lookup, delivery tracking, and HIPAA compliance. Treating notifications as "just send a message" would have produced a fragile, non-compliant system.

  5. The biggest ROI is often cultural, not technical. The claims team's ability to see their system in real time changed how they operate. Bottleneck detection, capacity planning, and process improvement all became possible because the system was observable.