EHR migration data-integrity checklist (full)
The complete validation checklist across all seven silent-data-loss failure modes. Each item is a concrete action to verify during migration, anchored to the governing standard.
FHIR R4 (v4.0.1) is the ONC/ASTP §170.315(g)(10) certification baseline; R5 was skipped for US regulatory purposes. R4 is the correct migration target as of 2026-06.
USCDI required baseline = v3 (mandated via HTI-1, effective Jan 1, 2026). Newer published: v4, v5, v6 (published Jul 24, 2025). Validate against the version your certification obligation names — not just the newest.
FHIR US Core: current published v9.0.0 (STU 9, 2026); the version named in the current g(10) requirement = US Core 6.1.0 (maps to USCDI v3). Target the cert-named version.
ICD-10-CM FY2026 edition, effective Oct 1, 2025 – Sep 30, 2026 (note the newer April 1 mid-year update cadence).
Structured → unstructured loss High-risk silent loss
Discrete, coded fields (labs, meds, problems) get migrated as scanned PDFs or free text — the values look present but become unqueryable and uncomputable. This can also implicate information-blocking obligations (EHI must remain electronically accessible).
- Per data-class reconciliation: confirm every USCDI element migrates as CODED, queryable data — not flattened into narrative text or a scanned image.
- Confirm the code-system URI (the `system`, not just code/display) survives — losing the binding is silent semantic loss even when the visible value looks intact.
- Spot-check that lab results, medications, and problems are still filterable/reportable in the target — run a query that depended on discreteness in the legacy system and confirm it returns the same rows.
- Confirm EHI that isn't in USCDI still migrates electronically (info-blocking scope is ALL EHI since Oct 6, 2022), not dumped to PDF.
Code-system mapping gaps High-risk silent loss
Crosswalking SNOMED CT, ICD-10-CM, RxNorm, LOINC, and CVX between EHRs is where meaning silently shifts: version drift, one-to-many ambiguity, RXCUI≠NDC, retired concepts, and codes landing in the wrong terminology slot.
- Local/proprietary codes never bound to a standard terminology will migrate as orphaned codes or free text — inventory and remediate them before cutover.
- Version drift: map historical data using the terminology release IN EFFECT WHEN RECORDED, then forward-map. Codes get retired/inactivated/re-parented across releases.
- One-to-many / many-to-one crosswalk ambiguity (GEMs, SNOMED↔ICD): auto-picking the 'first' target silently changes meaning — flag ambiguous maps for human review.
- RXCUI ≠ NDC: RXCUI is a normalized concept; NDC is packaging/manufacturer-specific (one RXCUI → many NDCs). Preserve both as separate related fields.
- Honor retired SNOMED concepts' historical-association refsets (SAME AS / REPLACED BY) — don't drop them.
- Validate codes land in the correct terminology slot (labs→LOINC not ICD; problems→SNOMED/ICD not LOINC).
- UMLS CUI is not a guarantee of semantic equivalence at your needed granularity — don't treat a CUI match as a clean map.
Allergy & problem-list granularity loss High-risk silent loss
Status and granularity fields default-flatten during migration. A refuted or entered-in-error allergy arriving as 'active', or a resolved problem reappearing as active, is a patient-safety event — not a cosmetic data issue.
- AllergyIntolerance: confirm `clinicalStatus` and `verificationStatus` (unconfirmed|confirmed|refuted|entered-in-error) do NOT default-flatten — a refuted/entered-in-error allergy migrating as active is a safety event.
- Confirm `reaction.manifestation` (the actual symptom) and per-reaction `severity` (mild|moderate|severe) and `criticality` (low|high|unable-to-assess) survive as distinct fields.
- Condition (problem list): preserve `category` so problem-list-items aren't merged with encounter-diagnoses or dropped.
- Preserve `clinicalStatus` (active|recurrence|relapse|inactive|remission|resolved) so resolved problems don't reappear as active.
- Confirm `onset[x]` / `abatement[x]` datatypes round-trip (date vs Period vs Age) without coercion.
Dropped HL7 v2 / FHIR interface feeds High-risk silent loss
Lab (ORU), registration (ADT), radiology, and pharmacy interfaces silently aren't reconnected after cutover — the classic migration failure where the data stops flowing and nobody notices for days.
- Reconcile that EVERY inbound/outbound interface (lab ORU, ADT registration, radiology, pharmacy) is reconnected AND tested post-cutover with a live message.
- Confirm Z-segments and custom OBX fields aren't dropped in translation.
- Verify MSH-9 trigger events map correctly (e.g., ADT^A01..A08) on the new engine.
- Confirm OBX units, reference ranges, and abnormal flags survive on result messages.
- Reconcile MRN crosswalks so messages route to the right patient; reconcile message counts source vs target for the cutover window.
Attachment / scanned-document loss Medium-risk silent loss
Document metadata migrates but the binary doesn't: broken or relative `attachment.url` pointers are the classic silent loss. For C-CDA, teams keep the human-readable narrative but lose the coded entries.
- Determine whether the source uses DocumentReference `content.attachment.url` (external pointer) vs inline `content.attachment.data` (base64) — broken/relative `url` pointers are the classic silent loss.
- Confirm `contentType` (MIME) and `docStatus` survive, and that Binary targets actually transfer and re-resolve in the target.
- For C-CDA: validate that STRUCTURED/CODED entries are parsed, not just the human-readable narrative (many migrations keep the text but lose the coded entries).
- Check C-CDA template conformance to the named version and that nullFlavors aren't converted into real values.
- Spot-open migrated scans/faxes/PDFs in the target to confirm they render, not just that the metadata row exists.
Audit-trail / access-log loss Medium-risk silent loss
Legacy access histories and audit logs are dropped at cutover — but the HIPAA 6-year retention obligation follows the DATA, not the system. You must still be able to produce historical access logs for records created in the legacy EHR.
- Confirm legacy audit logs / access histories are migrated OR retained in an accessible archive for the full 6-year window (45 CFR 164.316(b)(2)(i)).
- Verify audit-control mechanisms (45 CFR 164.312(b)) are operational on the TARGET system at go-live.
- Confirm you can still produce historical access logs for records created in the legacy system post-decommission.
USCDI / C-CDA portability completeness High-risk silent loss
Use the cert-named US Core / USCDI version as the minimum completeness checklist. Anything in USCDI that doesn't round-trip is, by definition, silent loss of portable data.
- Use the cert-named US Core / USCDI version (currently US Core 6.1.0 → USCDI v3) as the minimum completeness checklist — verify your obligation's named version.
- Reconcile every required USCDI element: row-count + coded-element + code-system-URI checks between source and target.
- Generate a C-CDA (CCD) from a sample patient in both systems and diff the coded entries, not just the rendered document.
- Document any USCDI element that doesn't round-trip and treat it as a defect, not an acceptable loss.