Skip to main content

Claims Service — Migration Plan

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · SERVICE_OVERVIEW · DOMAIN_MODEL

1. Background

The claims-service consolidates two legacy modules per ADR (see SERVICE_OVERVIEW):

Legacy moduleFR prefixWhat it owned
ADMIN-CLAIMSFR-CLM-*Claim assembly, scrubbing, submission, denial/appeal
ADMIN-INSFR-INS-*Coverage management, eligibility verification, prior authorization

FR mappings: all FR-CLM-* and FR-INS-* references are re-numbered as FR-CLAIMS-*. Legacy refs preserved in the FR mapping table for traceability.

2. Migration Scope

Migration concernDetail
Legacy billing / claims system dataExisting claim records (draft, submitted, paid, denied) migrate to claims.claim_records
Legacy insurance / coverage recordsPatient coverage records migrate to claims.coverages
Prior authorization recordsMigrate to claims.prior_authorizations
Remittance / ERA recordsHistorical ERAs migrate to claims.remittance_records
Payer onboarding configsLegacy payer configuration (EDI ISA/GS segments, API auth) migrates to claims.payer_configs
FHIR financial resourcesLegacy FHIR Claim and Coverage IDs re-mapped; redirect table active for 90 days

3. Migration Phases

Phase 0: Pre-Migration Audit

  • Audit legacy ADMIN-CLAIMS and ADMIN-INS databases for record counts, status distributions, schema gaps.
  • Identify claims in ambiguous legacy states (e.g., PENDING with no payer response > 90 days) — categorize as submitted with flag migration_stale.
  • Identify coverage records with overlapping effective dates for same patient/payer — resolve priority conflicts per CoveragePriority rules.
  • Catalog all legacy payer EDI configurations (ISA/GS segment values, X12 version, SFTP paths).
  • Identify any claims linked to encounters that no longer exist in scheduling-service (orphaned claims).

Phase 1: Schema Deployment

  • Deploy claims-service schema (claims PostgreSQL schema) alongside legacy schema.
  • Run initial Drizzle migrations — schema structure only, no data movement.
  • Validate RLS policies in staging with synthetic claim data.
  • Validate payer EDI adapter configuration import.

Phase 2: Coverage and Payer Onboarding Migration (Batch)

Coverage records are migrated first as they are referenced by claims:

-- Migrate legacy coverage / insurance records
INSERT INTO claims.coverages (
id, tenant_id, patient_id, payer_id, subscriber_id,
group_number, plan_name, priority, relationship,
effective_from, effective_to, copay_amount, copay_currency,
deductible_amount, status, created_at, updated_at
)
SELECT
'cov_' || legacy_ins.id,
legacy_ins.tenant_id,
legacy_ins.patient_id,
legacy_ins.payer_id,
legacy_ins.member_id,
legacy_ins.group_number,
legacy_ins.plan_description,
CASE legacy_ins.priority WHEN 1 THEN 'primary' WHEN 2 THEN 'secondary' ELSE 'tertiary' END,
LOWER(legacy_ins.relationship_to_subscriber),
legacy_ins.coverage_start_date,
legacy_ins.coverage_end_date,
legacy_ins.copay_amount,
COALESCE(legacy_ins.currency, 'AFN'),
legacy_ins.deductible_amount,
CASE WHEN legacy_ins.coverage_end_date IS NULL OR legacy_ins.coverage_end_date > NOW() THEN 'active' ELSE 'inactive' END,
legacy_ins.created_at,
legacy_ins.updated_at
FROM legacy_insurance.policies legacy_ins;

Payer config onboarding migration:

-- Seed payer configurations from legacy EDI settings
INSERT INTO claims.payer_configs (
id, tenant_id, payer_id, payer_name, submission_channel,
isa_sender_id, isa_receiver_id, gs_sender_id, gs_receiver_id,
sftp_host, sftp_path, is_active
)
SELECT
gen_random_uuid(), legacy.tenant_id, legacy.payer_code, legacy.payer_name,
CASE WHEN legacy.submission_mode = 'EDI' THEN 'x12_837'
WHEN legacy.submission_mode = 'API' THEN 'payer_rest'
ELSE 'x12_837' END,
legacy.isa_sender, legacy.isa_receiver,
legacy.gs_sender, legacy.gs_receiver,
legacy.sftp_hostname, legacy.sftp_upload_path, TRUE
FROM legacy_claims.payer_settings legacy;

Phase 3: Claim Records Migration (Batch)

-- Migrate historical claims
INSERT INTO claims.claim_records (
id, tenant_id, patient_id, encounter_id, coverage_id,
bill_provider_id, rendering_provider_id,
service_date_from, service_date_to,
diagnosis_codes, total_billed, status,
submission_channel, clearinghouse_ref, payer_claim_number,
version, created_at, updated_at
)
SELECT
'clm_' || legacy.claim_id,
legacy.tenant_id,
legacy.patient_id,
legacy.encounter_id,
'cov_' || legacy.coverage_id,
legacy.billing_npi,
legacy.rendering_npi,
legacy.service_date_from,
legacy.service_date_to,
to_jsonb(legacy.icd_codes),
legacy.billed_amount,
CASE legacy.claim_status
WHEN 'DRAFT' THEN 'draft'
WHEN 'SUBMITTED' THEN 'submitted'
WHEN 'ACCEPTED' THEN 'accepted'
WHEN 'PAID' THEN 'paid'
WHEN 'DENIED' THEN 'denied'
WHEN 'APPEALED' THEN 'appealed'
WHEN 'CLOSED' THEN 'closed'
ELSE 'draft'
END,
'x12_837',
legacy.clearinghouse_ref,
legacy.payer_claim_number,
1,
legacy.created_at,
legacy.updated_at
FROM legacy_claims.claims legacy;

Migration scripts summary:

StepScriptIdempotency
1. Migrate payer configsscripts/migrate-payer-configs.tsUpsert on payer_id + tenant_id
2. Migrate coverage recordsscripts/migrate-coverages.tsUpsert on id
3. Migrate prior authorizationsscripts/migrate-prior-auths.tsUpsert on id
4. Migrate claim recordsscripts/migrate-claims.tsUpsert on id
5. Migrate remittance recordsscripts/migrate-remittances.tsUpsert on id
6. Migrate denial casesscripts/migrate-denials.tsUpsert on id
7. Validate row countsscripts/validate-claims-migration.tsCount comparison report
8. Generate FHIR ID redirect manifestscripts/generate-fhir-claims-redirect.tsID map CSV

Phase 4: Batch Claim Re-Processing

Some legacy claims may be in a PENDING / UNKNOWN status without a definitive payer response. These require re-processing:

  1. Query all migrated claims with migration_stale flag where status = 'submitted' and submittedAt < NOW() - 90 days.
  2. Run eligibility re-check via POST /v1/claims/:id/recheck-eligibility.
  3. For claims > 1 year old with no response, mark as closed with reason MIGRATION_NO_RESPONSE after clinical billing review.
  4. For re-submittable claims (within payer filing limit): create corrected claim and submit via new adapter.

Phase 5: Payer Onboarding Validation

For each payer in claims.payer_configs:

  1. Send test X12 270 (eligibility request) and verify 271 response.
  2. Send test X12 837 (claim) in test mode and verify 999/277 acknowledgement.
  3. Sign off from billing operations team before activating payer in production.

Phase 6: Cut-Over

StepAction
Stop writes to legacy claims systemFeature flag LEGACY_CLAIMS_WRITE=false
Run final delta sync (records created after Phase 3 snapshot)Delta migration scripts with timestamp filter
Validate record counts (0 discrepancy threshold)Automated script
Switch read and write traffic to claims-serviceKong route weight: 100% new service
Activate FHIR Claim and Coverage resources via interop-serviceNew R4 FHIR IDs; legacy IDs → 301 redirect for 90 days
Archive legacy systemSet replicas to 0; DB read-only for 90 days

4. Payer Onboarding Process (New Payers Post-Migration)

After GA, new payer onboarding follows this flow:

5. Coverage Record Import from Existing Insurance Databases

For tenants with pre-existing patient insurance data in external systems:

Import methodUse caseAPI / Tool
CSV batch importLarge-scale coverage import (> 1000 records)POST /v1/coverages/batch-import (multipart CSV)
FHIR Coverage resource importFHIR-capable source systemsPOST /fhir/R4/Coverage via interop-service
Manual entrySmall practices, individual recordsPOST /v1/coverages standard REST
X12 834 enrollment feedGroup insurance enrollment filesAdapter in interop-service (backlog)

CSV import template columns: patient_id, payer_id, subscriber_id, group_number, plan_name, priority, relationship, effective_from, effective_to, copay_amount, currency.

6. Rollback Plan

TriggerRollback action
Migration count mismatch > 0.1%Halt cutover; investigate delta; re-run migration
Claim submission failure rate > 0.5% post-cutoverKong route back to legacy; page billing ops
Payer EDI adapter producing malformed 837Disable affected payer config; page integration team
FHIR Coverage ID mismatch in patient portalRe-run FHIR redirect manifest; extend redirect window

Legacy DB preserved read-only for 90 days post-cutover. Rollback runbook: infra/runbooks/claims-migration-rollback.md.

7. Legacy FR Mapping

New FRLegacy FRSource module
FR-CLAIMS-001FR-CLM-001ADMIN-CLAIMS
FR-CLAIMS-002FR-CLM-002ADMIN-CLAIMS
FR-CLAIMS-010FR-INS-001ADMIN-INS
FR-CLAIMS-011FR-INS-002ADMIN-INS
FR-CLAIMS-012FR-INS-003ADMIN-INS

8. Open Questions

  • Confirm payer filing limit rules per country (AFG/UAE) — affects re-processing decision for stale claims.
  • X12 834 enrollment feed adapter scope — confirm if needed for M1 or deferred.