Skip to main content

Terminology Service — Migration Plan

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services

1. Migration Context​

The terminology-service is a new shared platform service. Migrations cover:

  1. Initial licensed terminology data load (all tenants share global data).
  2. Tenant-scoped custom concept migration from legacy coded-value lists.
  3. Drug interaction / CDS data migration from any prior clinical decision support component.

2. Initial Licensed Terminology Load (ETL)​

All new deployments must run the terminology ETL pipeline before the service is ready to accept traffic. The ETL runs as a Kubernetes Job.

PhaseActionTool
1. Data procurementObtain licensed data files (LOINC CSV, SNOMED RF2, RxNorm RRF) from respective sourcesManual / license portal
2. Data stagingUpload to secured object storage bucket (terminology-etl-input/{env}/)AWS S3 / compatible
3. Schema migrationRun Drizzle migrations: pnpm db:migrateCI/CD pipeline
4. ETL importExecute Kubernetes ETL jobs in order: LOINC → SNOMED → RxNorm → ICD-10kubectl apply -f kubernetes/jobs/terminology-etl/
5. Drug data importLoad drug interaction, drug class, and contraindication data from licensed clinical knowledge sourceETL job: rxnorm-cds-import.job.yaml
6. Value set seedingSeed standard FHIR value sets (obs-interpretation, condition-category, etc.)pnpm db:seed:valuesets
7. Readiness verificationCheck GET /health returns terminology_data: loaded; spot-check $lookup for known codesManual / smoke test

3. Tenant Custom Concept Migration​

For tenants with existing facility-specific coded value lists:

StepAction
ExportExport legacy custom codes to CSV: id, system, code, display, definition
ValidateRun scripts/migration/terminology/validate-custom-concepts.ts — checks for duplicates and invalid system URIs
ImportPOST /internal/terminology/import with system = urn:ghasi:tenant:{tenantId}
VerifySpot-check GET /v1/terminology/search?system=urn:ghasi:tenant:{tenantId}&query=...

Migration script: scripts/migration/terminology/import-tenant-concepts.ts

The import is idempotent (upsert on tenant_id + system + code). Pre-existing global concepts with the same code are not overwritten.


4. Drug Interaction Data Migration​

If a prior clinical system had drug interaction data in a proprietary schema, migrate it as follows:

  1. Export interactions to CSV: drug1_code, drug2_code, severity, description
  2. Normalize: ensure drug1_code <= drug2_code (canonical pair ordering).
  3. Import via ETL: pnpm db:seed:interactions --file interactions.csv
  4. Validate severity coverage for CONTRAINDICATED and HIGH pairs with a known test set.

5. Rolling Terminology Updates​

After initial deployment, terminology datasets receive periodic updates (LOINC releases annually, SNOMED CT twice yearly). The update process:

  1. Upload new licensed data files to staging bucket.
  2. Re-run the relevant ETL Kubernetes Job.
  3. ETL performs upsert (no concept deletions — deactivation only).
  4. TERMINOLOGY.dataset.updated event is published; downstream consumers may invalidate cached concept data.
  5. Monitor concept count metrics post-import; verify no unexpected drops.

6. Rollback Plan​

ScenarioRollback action
ETL import corrupts concept dataRestore PostgreSQL from pre-import snapshot; re-run corrected ETL
Schema migration failureDrizzle supports down migrations; run pnpm db:migrate:down to previous version
New version causes lookup regressionsRoll back Kubernetes deployment to previous image; ETL data is independent of service version

ETL jobs run in a transaction where possible (PostgreSQL COPY with ROLLBACK on error). Partial imports that abort do not leave orphaned records.