Skip to main content

Patient Chart Service — Migration Plan

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · SERVICE_OVERVIEW §11 Source Reconciliation

1. Migration context

The patient-chart-service consolidates five legacy modules — patient-chart, problem-list, allergies, vitals, and clinical-notes — each previously operating as a separate module with its own schema prefix, outbox, and NATS subjects. This migration plan covers:

  1. Data migration from five legacy schemas into the unified patient_chart schema.
  2. NATS subject migration from legacy patterns to canonical patient_chart.{aggregate}.{event}.v{N}.
  3. Consumer service cutover from legacy REST paths to the new unified API surface.
  4. Decommissioning of legacy modules post-migration.

2. Legacy state inventory

Legacy moduleDB schema/prefixNATS subjectsAPI prefixStatus
patient-chartchart.*CHART.*/api/v1/chart/*Consolidate → patient_chart
problem-listproblems.*PROBLEMS.*/api/v1/problems-legacy/*Consolidate
allergiesallergies.*ALLERGIES.*/api/v1/allergies-legacy/*Consolidate
vitalsvitals.*VITALS.*/api/v1/vitals-legacy/*Consolidate
clinical-notesnotes.*CLINICAL_NOTES.*/api/v1/notes-legacy/*Consolidate

3. Migration phases


4. Data migration tasks

Phase 1 — Schema and data migration

TaskDescriptionRollback
Create patient_chart schemaDrizzle migration; no data yetDrop schema (no data)
Migrate problems.*patient_chart.problemETL script; maps legacy ids to prb_* ULID; preserves history in problem_history_entryRestore from pre-migration snapshot
Migrate allergies.*patient_chart.allergyMap to alg_* ULID; preserve allergy_reaction sub-rowsSnapshot restore
Migrate vitals.*patient_chart.vitals_set + observationMap measurement rows to per-observation model; group by recorded_at + patient_id + recorder_idSnapshot restore
Migrate notes.*patient_chart.clinical_note + note_section + note_signatureMap status values; preserve cosign recordsSnapshot restore

ID remapping table: A legacy_id_map table in the migration schema tracks (legacy_module, legacy_id) → new_ulid for foreign-key re-stitching and cross-reference lookups during transition.

Phase 2 — Dual-publish NATS subjects

During M0→M1, the service publishes events on BOTH legacy and canonical subjects:

Legacy subjectCanonical subjectDual-publish until
PROBLEMS.PROBLEM.ADDEDpatient_chart.problem.added.v1End of M1
PROBLEMS.PROBLEM.UPDATEDpatient_chart.problem.updated.v1End of M1
ALLERGIES.ALLERGY.ADDEDpatient_chart.allergy.added.v1End of M1
VITALS.VITALS_SET.RECORDEDpatient_chart.vitals.recorded.v1End of M1
CLINICAL_NOTES.NOTE.SIGNEDpatient_chart.note.signed.v1End of M1

After M1 consumer cutover is confirmed, dual-publish is disabled and legacy subjects are deprecated.


5. API migration

Legacy pathNew pathChange
GET /api/v1/problems-legacy/:idGET /v1/problems/:idNew response shape (FHIR-aligned)
POST /api/v1/problems-legacyPOST /v1/problemsRenamed + schema changes
GET /api/v1/allergies-legacy/:patientIdGET /v1/allergies?patientId=Query param-based
POST /api/v1/vitals-legacyPOST /v1/vitalsPanel payload shape
POST /api/v1/notes-legacy/draftPOST /v1/clinical-notesUnified note create

Kong routes updated to forward traffic to new paths; legacy routes kept active until M1 consumer cutover.


6. Consumer service cutover

ConsumerLegacy event / API usedNew event / APICutover milestone
medication-serviceALLERGIES.ALLERGY.ADDEDpatient_chart.allergy.added.v1M1
orders-serviceGET /api/v1/allergies-legacy/advisoryGET /v1/allergies/advisoryM1
population-health-servicePROBLEMS.*, VITALS.*patient_chart.problem.*, patient_chart.vitals.*M1
patient-portal-serviceLegacy chart read APIsNew /v1/chart/*, /v1/problems/*, etc.M1
interop-service (FHIR)Condition, AllergyIntolerance, Observation FHIR readsSame paths via new serviceNo change (FHIR paths unchanged)

7. Tenant migration notes

  • All existing tenants have their chart data migrated in Phase 1 with zero downtime (read path from legacy; write path switched after validation).
  • The legacy_id_map table is kept alive for 90 days post-cutover for cross-reference lookups, then archived.
  • Tenants using FHIR read surface see no disruption; interop-service FHIR paths are unchanged.

8. Rollback plan

PhaseRollback actionData loss risk
Phase 1 (data migration)Restore pre-migration DB snapshot; re-point Kong to legacy modulesZero — snapshot taken immediately before
Phase 2 (dual-publish)Disable canonical subject publish; revert to legacy subjectsZero — legacy consumers unaffected during dual-publish
Phase 3 (API cutover)Re-enable legacy Kong routes; dual-publish restoredZero — traffic falls back to legacy

9. Open questions

  • Confirm vitals grouping heuristic: what defines a VitalsSet boundary for legacy ungrouped measurements?
  • Determine fate of requisitions-referrals cross-links in clinical-notes (legacy ADR-0046 redirected to orders-service).