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.