Payer priority and Medicaid-last-resort ops
Outcome
Medicare Secondary Payer (MSP) ordering is correct after enrollment changes; state-specific Medicaid non-cover CARCs gate secondary generation appropriately.
Prerequisites
- Familiarity with MSP rules (Working-aged, ESRD, Disability, Black Lung).
- Write access to
member.coverage_policyandrcm_reference.medicaid_non_covered_carc.
Two guards on top of the COB waterfall
Both guards run inside processSecondaryClaimWaterfallDetailed and can be
toggled via WaterfallOptions — they default to on.
| Guard | What it does | When |
|---|---|---|
| MSP reorder | Reads member's medicare_entitlement_reason + esrd_coordination_start_date + employer_size + has_black_lung_benefit and reorders coverages so the primary payer follows MSP rules. | Every waterfall invocation. |
| Medicaid last resort | Suppresses Medicaid as secondary if the primary's denial CARC is on rcm_reference.medicaid_non_covered_carc. | When the candidate secondary is Medicaid (MEDICAID_FFS or MEDICAID_MCO). |
Re-evaluate payer priority after enrollment change
Member enrollment changes (a new EGHP, an ESRD coordination date, a working-aged transition, loss of Black Lung benefit) do not re-fire MSP classification automatically for already-submitted claims.
For a claim whose secondary hasn't been generated yet:
Update the member's coverage policy with the new context:
UPDATE member.coverage_policySET medicare_entitlement_reason = 'ESRD',esrd_coordination_start_date = '2026-04-01',employer_size = 25,has_black_lung_benefit = falseWHERE policy_id = '<id>';Re-call the waterfall for any pending claim. The classifier reloads
rcm_reference.medicare_primary_ruleon every call, so the new context is picked up immediately:await processSecondaryClaimWaterfallDetailed(db, input, actor);If a secondary already exists, do not regenerate. The path is the same rare-event manual dance described in §3.3 COB adjustment snapshot.
Add a state-specific Medicaid non-cover CARC
When a state plan publishes a new non-cover CARC that the federal baseline
doesn't yet block, insert a row into
rcm_reference.medicaid_non_covered_carc:
INSERT INTO rcm_reference.medicaid_non_covered_carc
(state_code, carc_code, reason_description, effective_from)
VALUES
('TX', 'B7',
'Service denied as not covered under Texas Medicaid non-emergent transport policy',
'2026-05-01');
State rows win over federal rows for the same CARC. No service restart needed — the guard reloads the list on every waterfall invocation.
Audit a suppression
A secondary suppressed by the Medicaid guard surfaces as
WaterfallOutcome { kind: 'SUPPRESSED', reason: 'medicaid-last-resort: CARC 204 (...)' }.
The reason string carries both the blocking CARC and whether a state
override or the federal baseline fired.
For post-hoc analysis, grep the claim_status_history.details JSON —
suppressions aren't persisted to denial_record because no escalation
happened.
SELECT claim_id, changed_at, details
FROM billing.claim_status_history
WHERE details::text LIKE '%medicaid-last-resort%'
AND changed_at > NOW() - INTERVAL '30 days'
ORDER BY changed_at DESC;
Validation
| Check | Expected |
|---|---|
| MSP reorder picks the right primary | Match policy in payer-priority rules |
| State CARC seed | Visible in medicaid_non_covered_carc |
| Suppressed waterfall | Reason in claim_status_history.details |
Known limits
- Medicaid state-code source. The guard reads
rcm_master.payer.stateto decide state-vs-federal match. Payers missingstatefall back to federal-only rows — verify Medicaid MCO payer rows havestateset before seeding state overrides. - CARC code format. Seeds are bare numeric codes (
'204'); the guard compares againstdenial_record.carc_codesverbatim. If the poster ever starts prefixingCO-/PR-/OA-, the seed list needs to migrate. - Pre-submission re-routing. This guards secondary generation. A claim wrongly filed against Medicare as primary (when MSP says the EGHP should be primary) isn't re-routed — that's tertiary-waterfall scope.
Cross-references
- Tertiary waterfall and resume for the next escalation step.
- Configure a new payer
to set
payer.statecorrectly.