Blog

Migration Usually Means Translation, Not Replacement

Almost no organization retires HL7 v2 when it adopts FHIR. What actually happens is that v2 keeps flowing between clinical systems while a translation layer produces FHIR...

Arinder Singh SuriArinder Singh Suri|September 10, 2026·11 min read

Almost no organization retires HL7 v2 when it adopts FHIR. What actually happens is that v2 keeps flowing between clinical systems while a translation layer produces FHIR resources for applications, APIs, and analytics. Calling that migration is imprecise but harmless, provided everyone understands the implication: you are building and maintaining a mapping indefinitely, not executing a one-time conversion. That reframing changes the engineering approach considerably, because a permanent translation layer needs versioning, test coverage, and reconciliation in a way a cutover project does not.

The Feed Keeps Running

Source systems continue emitting v2 messages. Your mapping consumes them, produces resources, and must handle every message the interface has ever produced, including the malformed ones.

One Direction of Authority

Decide per data domain whether v2 or FHIR is authoritative. Bidirectional translation through separate mapping layers drifts apart and produces disagreements that are expensive to reconcile.

Mappings Are Long-Lived Code

Treat transformation logic as a maintained codebase with tests, not as configuration inside an interface engine that nobody documents. Interface engine scripts are where institutional knowledge goes to die.

Architecture Comes First

Which pattern you use, facade, event bridge, or parallel operation, determines what the mapping must produce. Our HL7 and FHIR integration page covers those architecture choices.

Fundamentals If You Need Them

Teams new to either standard should start with the basics rather than mapping tables. Our healthcare integration guide covers HL7 v2, FHIR, and Mirth Connect from the ground up.

The HL7 v2-to-FHIR Implementation Guide and How to Use It

HL7 publishes a v2-to-FHIR implementation guide through its Orders and Observations work group, currently at version 1.0.0 as a Standard for Trial Use, with mappings organized by v2 chapter. It is the correct starting point and it is not a complete answer. The guide provides standard mappings for standard content, which means everything conforming to the base standard is covered and everything specific to your site is not. Read it as a well-researched default that you will deviate from deliberately and document each time you do.

Four Layers of Mapping

The guide separates datatype maps, segment maps, message maps, and code system concept maps. Working at the wrong layer is a common early mistake that produces inconsistent transformation logic.

Datatype Maps Come First

HL7 v2 datatypes such as XPN, XAD, CX, and CE map to FHIR datatypes like HumanName, Address, Identifier, and CodeableConcept. Get these right once and reuse them everywhere.

Segment Maps Are the Working Layer

Each segment maps to one or more resource elements. This is where most implementation effort lands and where the guide is most directly useful day to day.

Message Maps Define the Bundle

A trigger event produces a set of related resources. Message maps describe that composition, which matters because downstream consumers receive bundles rather than isolated resources.

Standards Status Is Informative

Much of the mapping content carries informative rather than normative status. It is guidance, not conformance requirement, so document your deviations rather than assuming the guide is binding.

Treat It as a Baseline

Fork the guide’s mappings into your own maintained specification. Referencing an external evolving document as your source of truth makes your transformation logic untestable.

Segment-Level Mapping: The Ones You Will Actually Build

Most integrations touch a small set of segments repeatedly. Building these correctly and reusing them covers the majority of real traffic, and getting them subtly wrong propagates errors across every message type. The recurring difficulty is that v2 segments carry more contextual meaning than their FHIR counterparts express directly. PV1 is not simply an Encounter, it carries attending provider, admission source, financial class, and location, each of which lands in a different place in FHIR. Mapping is decomposition, not field copying.

PID to Patient

Names, identifiers, birth date, address, and phone map to Patient. PID-3 requires careful identifier system assignment, since an MRN without a namespace is not usefully distinguishable.

PV1 to Encounter and More

Encounter class, period, and location come from PV1, while attending and referring providers become Encounter.participant references and financial class often lands in Coverage or an extension.

OBX to Observation

Each OBX becomes an Observation with OBX-3 as the code, OBX-5 as the value, and OBX-11 driving status. Value type in OBX-2 determines which FHIR value element you populate.

OBR to DiagnosticReport or ServiceRequest

OBR carries both order and report context depending on message type. In ORU it contributes to DiagnosticReport; in order messages it contributes to ServiceRequest.

DG1 and PR1 to Condition and Procedure

Diagnosis and procedure segments map to Condition and Procedure, with careful attention to whether the coding is billing-oriented or clinically asserted, since that affects category assignment.

AL1 to AllergyIntolerance

Allergy segments map reasonably cleanly, though severity and reaction coding are frequently local and require concept mapping rather than direct translation.

Message-Level Mapping by Trigger Event

Working at message level is what produces usable output, because consumers need coherent bundles rather than resource fragments. A single ORU message routinely yields a DiagnosticReport, several Observations, a Specimen, and Provenance, all referencing each other correctly. Getting references right is the hard part: resources must point at each other using identifiers that resolve, which requires resolving patient and encounter identity before constructing the bundle rather than during it. Order of operations matters more than mapping accuracy at this layer.

ADT to Patient and Encounter

A01, A03, A04, and A08 maintain Patient and Encounter state. Deciding which events to process is an early design decision, since most integrations act on a subset rather than all fifty-plus events.

The Merge Event Needs Special Handling

A40 patient merge maps to Patient.link with a replaced-by relationship rather than deletion. Mishandling merges produces duplicate patients that are painful to unwind later.

ORU to DiagnosticReport Bundles

Result messages produce a DiagnosticReport referencing multiple Observations, with Specimen and performer references. The report-to-observation relationship must be constructed, not inferred by consumers.

ORM and OML to ServiceRequest

Order messages become ServiceRequest with requester, intent, and priority. Order control codes in ORC-1 determine whether you are creating, updating, or cancelling.

SIU to Appointment

Scheduling messages map to Appointment and related resources, with the schedule and slot model frequently requiring simplification since v2 scheduling is more granular.

ADT Depth If You Need It

Event selection and the awkward update and merge cases deserve their own treatment. Our HL7 ADT messages explained post covers the event set in detail.

Identifiers and Terminology: The Two Things That Break Everything

If a v2 to FHIR project fails, it usually fails on one of these two, and both are analysis problems rather than coding problems. Identifiers fail because v2 carries MRNs, account numbers, and visit numbers without global namespaces, and FHIR requires a system URI to disambiguate them. Terminology fails because local codes in OBX-3, DG1-3, and RXE fields must resolve to LOINC, SNOMED CT, and RxNorm, and that mapping is never complete on day one. Both need dedicated ownership and ongoing maintenance rather than a one-time effort during build.

Assign Identifier Systems Deliberately

Every identifier type needs a documented system URI. Two facilities using overlapping MRN ranges without distinct namespaces will silently merge different patients.

Resolve Identity Before Constructing Resources

Patient and encounter lookup must happen before bundle assembly. Creating resources first and reconciling later produces duplicates at a rate proportional to message volume.

Local Codes Need Concept Maps

Store local-to-standard code mappings in a terminology service or ConceptMap resources. Hardcoding them in transformation scripts guarantees they diverge from clinical reality.

LOINC for Observations, Specifically

OBX-3 frequently carries local lab codes. Mapping these to LOINC is ongoing work driven by the lab’s test catalog, which changes without notifying the integration team.

Unmapped Codes Need a Policy

Decide what happens when a code has no mapping: reject, pass through as local coding, or flag for review. Silent dropping is the most common and worst option.

US Core Constrains Your Output

Producing raw FHIR is insufficient for United States use. Our FHIR R4 implementation guide covers US Core conformance expectations.

Z-Segments and Everything the Standard Does Not Cover

Every real v2 interface carries local content. Z-segments are custom by definition and have no standard meaning, which is why v2 interfaces are rarely portable between organizations without rework. The same applies to overloaded standard fields, where a site has used a spare component for something it was never intended to carry. This content is not optional to handle, because it frequently contains exactly the data a downstream application needs. What matters is that each decision is explicit and recorded.

Three Valid Decisions Per Segment

Each Z-segment either maps to a standard FHIR element, maps to a documented extension, or is deliberately dropped. All three are defensible; undocumented handling is not.

Extensions Need Definitions

If you create FHIR extensions, define them properly with canonical URLs. Ad hoc extensions without definitions are unusable by any consumer other than the team that created them.

Watch for Overloaded Standard Fields

Sites commonly repurpose unused components of standard segments. These are harder to spot than Z-segments because the field appears standard while carrying non-standard content.

Inventory Before Mapping

Sample real production traffic to find what is actually present, rather than mapping from the interface specification. The specification and the traffic routinely disagree.

Retain the Original Message

Keep raw v2 alongside derived resources. Mapping corrections, audits, and reprocessing all require the original, and regenerating v2 from FHIR is not lossless.

Testing and Validating a Mapping Before It Goes Live

Mapping correctness cannot be established by reading code. It requires running real message samples through the transformation and validating both structural conformance and semantic accuracy, which are different checks. Structural validation confirms the output is valid FHIR against the applicable profiles. Semantic validation confirms the output means what the input meant, and only a clinician or clinical analyst can confirm that. Projects that run the first check and skip the second ship mappings that validate cleanly and misrepresent clinical data.

Build a Regression Corpus

Collect production message samples covering every message type, every trigger event in scope, and the known malformed cases. Run the full set on every mapping change.

Validate Against Profiles

Use the FHIR validator against US Core and any local profiles. Structural validity is table stakes and catches a meaningful proportion of mapping errors cheaply.

Get Clinical Review of Output

Have a clinical analyst compare source messages against generated resources for a sample. Semantic errors that pass structural validation are the expensive category.

Test the Failure Paths

Confirm behavior on missing required fields, unmapped codes, and unresolvable identifiers. Error handling is where undertested mappings cause silent data loss.

Reconcile Counts in Production

Compare message counts against resource counts on an ongoing basis. Divergence indicates messages being dropped somewhere, which is a patient safety issue as much as a data one.

Where the Transformation Runs

Interface engines handle most of this in practice. Our Mirth Connect channel development tutorial covers channel and transformer construction.

Frequently Asked Questions About v2 to FHIR Migration

These questions come up in nearly every mapping project, usually after a first pass has produced output that validates but does not look right to a clinical reviewer. Answers reflect standards status as of September 2026. The v2-to-FHIR implementation guide continues to develop, so check the current published version before treating any mapping as settled, particularly for chapters outside the commonly used message types.

Is there an official HL7 v2 to FHIR mapping?

Yes. HL7 publishes a v2-to-FHIR implementation guide through the Orders and Observations work group, organized by v2 chapter. Much of its content carries informative rather than normative status.

Can the mapping be automated?

Standard segments largely can. Local Z-segments, overloaded fields, identifier namespaces, and local terminology require site-specific analysis that no tool can infer from message content.

Does one v2 message become one FHIR resource?

No. A single ORU commonly produces a DiagnosticReport, multiple Observations, a Specimen, and Provenance, assembled as a bundle with correct internal references.

What happens to Z-segments?

Each needs an explicit decision: map to a standard element, map to a defined extension, or deliberately drop. Undocumented handling is the most common cause of silent data loss.

How do we handle patient merges?

A40 maps to Patient.link with a replaced-by relationship rather than record deletion. Mishandled merges create duplicates that become progressively harder to reconcile.

Do we still need an interface engine?

Usually yes. Engines handle v2 routing, acknowledgment, retry, and alerting that FHIR APIs do not provide, and the transformation itself commonly runs there.

How long does a mapping project take?

Terminology mapping and clinical validation dominate the timeline rather than transformation development. A contained scope typically runs three to six months, with terminology work continuing afterward.

Ready to Discuss Your Project With Us?

Your email address will not be published. Required fields are marked *

What's Next?

Our expert reaches out shortly after receiving your request and analyzing your requirements.

If needed, we sign an NDA to protect your privacy.

We request additional information to better understand and analyze your project.

We schedule a call to discuss your project, goals. and priorities, and provide preliminary feedback.

If you're satisfied, we finalize the agreement and start your project.