Use FHIR for new API-first projects, mandated patient and payer APIs, and any interface where query-based access or external app connectivity is required. Keep HL7 v2 for high-volume, low-latency event feeds and stable legacy integrations where your trading partners have no FHIR capability. For most health systems and laboratories operating today, the honest answer is both, connected through an integration engine that translates between them. ONC and CMS mandates have made FHIR-based APIs a compliance requirement for patient access and payer data exchange, while HL7 v2 remains a dominant format for real-time clinical traffic in many production hospital environments. Run an interface-by-interface decision checklist (see the decision rules section below) before committing to a migration path for any given feed.
Table of Contents
- How do FHIR and HL7 v2 compare at a glance?
- What is HL7 v2 and why does it still run most hospital traffic?
- What is FHIR and what makes it the right choice for modern APIs?
- Where HL7 v2 and FHIR share common ground
- What are the technical differences that affect your mappings?
- Concrete mapping examples: lab results, medication orders, and ADT flows
- How to plan and run an HL7 v2 to FHIR migration
- When should you choose FHIR, keep HL7 v2, or build a hybrid?
- How does a modern PGx platform integrate HL7 v2 and FHIR?
- Key Takeaways
- The case for governance over tooling in hybrid HL7 environments
- Signalpgx gives labs FHIR-ready PGx reporting without replacing your v2 infrastructure
- Authoritative references and implementation resources
How do FHIR and HL7 v2 compare at a glance?
The table below covers the dimensions that matter most during interface planning. Cells marked with an asterisk require per-interface validation because the answer varies by site, vendor, or message type.
| Dimension | HL7 v2 | FHIR (R4 / R4B) |
|---|---|---|
| Data model | Message/event-driven; flat pipe-delimited segments (MSH, PID, OBR, OBX…) | Resource graph; linked resources (Patient, Observation, DiagnosticReport…) |
| Transport / APIs | MLLP over TCP, file drop, SFTP | HTTPS/REST, SMART on FHIR, CDS Hooks |
| Encoding | ER7 (pipe-delimited), legacy XML | JSON (primary), XML, RDF/Turtle |
| Extensibility / profiling | Z-segments, site-specific optional fields, local tables | FHIR extensions, StructureDefinitions, Implementation Guides |
| Vocabularies | Local code tables (user-defined tables), LOINC/SNOMED where adopted | CodeableConcept with canonical code systems (LOINC, SNOMED CT, RxNorm); terminology services |
| Cardinality | Loose; many fields optional or repeating; no enforcement at transport layer | Defined per profile; required fields enforced by validators; cardinality mismatches are a primary mapping risk* |
| Tooling & ecosystem | Mature parsers (Mirth Connect, Rhapsody, Iguana, Azure Health Data Services); limited formal validators | Growing validators (HAPI FHIR, Inferno, Touchstone); rich IG ecosystem; test harnesses available |
| Maturity / adoption | decades in production; dominant for internal event streams | Mandated for new patient/payer APIs; rapidly expanding for external exchange |
| Migration effort | Baseline (existing) | Moderate to high per interface; use HL7 v2→FHIR IG as starting point |
| Regulatory fit | Adequate for internal/lab reporting; not sufficient for ONC/CMS patient access mandates | Required for ONC 21st Century Cures Act APIs, CMS interoperability rules, and patient-facing apps |
Cardinality mismatches and missing required fields are the most common source of data loss during translation. Validate each interface individually.
The HL7 v2→FHIR Implementation Guide provides segment maps and mapping spreadsheets that serve as the authoritative starting point for any translation project, though every production interface will require site-specific profiling decisions on top of those baseline maps.
What is HL7 v2 and why does it still run most hospital traffic?
HL7 Version 2 was first published in 1987 and designed around a simple, pragmatic goal: move clinical events between systems in near real time over unreliable hospital networks. Its pipe-delimited, segment-based message format was easy to parse with minimal compute, and MLLP (Minimal Lower Layer Protocol) over TCP gave it reliable framing without requiring a full HTTP stack. That combination proved durable. Three decades later, HL7 v2 remains the dominant wire format for internal clinical event streams in U.S. hospitals and laboratories.
Common v2 message types and their operational contexts
| Message Type | Event | Typical Use |
|---|---|---|
| ADT^A01 / A08 | Admit / Update | Patient registration, census feeds, downstream system sync |
| ORU^R01 | Observation Result | Lab results, vitals, point-of-care results to ordering system or EHR |
| ORM^O01 | Order Message | Medication and diagnostic orders from EHR to ancillary systems |
| SIU^S12 | Scheduling | Appointment creation and updates |
| MDM^Txx | Medical Document | Transcription, clinical notes |
HL7 v2's operational strengths are real. It handles thousands of messages per minute without HTTP overhead, tolerates lossy networks through MLLP ACK/NACK retry semantics, and integrates with virtually every EHR, LIS, and ancillary system sold in the U.S. market. The CDC's laboratory data reporting guidance relies on HL7 v2 ORU messages for public-health lab result transport, which illustrates how deeply the format is embedded in regulated workflows.
The format's weaknesses are equally real. Z-segments (custom segments outside the standard) proliferate across sites, making interfaces brittle and vendor-specific. Local code tables replace canonical terminologies in many implementations, complicating downstream analytics. There is no native query mechanism: v2 is push-only, which means a consumer cannot ask "give me all results for patient X" without a separate query interface.
A minimal ORU^R01 snippet (annotated)
MSH|^~\&|LAB|HOSPITAL|EHR|HOSPITAL|20240315120000||ORU^R01|MSG001|P|2.5.1
PID|1||MRN12345^^^HOSPITAL^MR||Smith^John^A||19800101|M
OBR|1|ORD001|LAB001|85025^CBC^LN|||20240315110000
OBX|1|NM|718-7^Hemoglobin^LN||14.2|g/dL|13.5-17.5|N|||F
Key fields for FHIR mapping: PID-3 (patient identifier) → Patient.identifier; OBX-3 (LOINC code) → Observation.code; OBX-5 (value) → Observation.valueQuantity; OBX-8 (abnormal flag) → Observation.interpretation. The timestamp in OBX-14 or OBR-7 maps to Observation.effectiveDateTime and requires conversion from v2 DTM format (YYYYMMDDHHMMSS) to ISO 8601.
What is FHIR and what makes it the right choice for modern APIs?
FHIR (Fast Healthcare Interoperability Resources) was published by HL7 International starting in 2014, with R4 becoming the stable, widely implemented version and R4B and R5 extending it further. The design philosophy shifted from event-driven messages to a resource graph: discrete, addressable clinical objects (Patient, Observation, MedicationRequest, DiagnosticReport, and roughly 150 others) exposed over standard HTTPS/REST endpoints. Each resource carries a canonical URL, supports versioning, and can be bundled for atomic transactions.
Core FHIR capabilities that matter to implementers
- CDS Hooks: — A lightweight webhook protocol for embedding real-time clinical decision support into EHR workflows at defined hook points (patient-chart-opened, order-select, etc.).
The HL7 FHIR specification is the authoritative reference for all resource definitions, search parameters, and operation signatures. The ONC/HealthIT.gov FHIR fact sheet documents the regulatory context: the 21st Century Cures Act and ONC's information-blocking rules require certified EHR technology to expose FHIR R4 APIs for patient access, making FHIR adoption a compliance matter for any system seeking ONC certification or participating in CMS interoperability programs.
A compact FHIR Observation resource (annotated)
{
"resourceType": "Observation",
"id": "hemoglobin-001",
"status": "final",
"category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "laboratory"}]}],
"code": {"coding": [{"system": "http://loinc.org", "code": "718-7",
"display": "Hemoglobin [Mass/volume] in Blood"}]},
"subject": {"reference": "Patient/MRN12345"},
"effectiveDateTime": "2024-03-15T11:00:00Z",
"valueQuantity": {"value": 14.2, "unit": "g/dL",
"system": "http://unitsofmeasure.org", "code": "g/dL"},
"interpretation": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation",
"code": "N", "display": "Normal"}]}]
}
Compare this to the ORU snippet above: the LOINC code (718-7) maps directly, the value and unit carry explicit system URIs (UCUM), and the patient reference is a resolvable FHIR resource link rather than a local MRN string. That referential integrity is what makes FHIR queryable and composable in ways v2 is not.
| FHIR Feature | Regulatory / Operational Driver |
|---|---|
| SMART on FHIR | ONC patient access API requirement |
| US Core profiles | Baseline for certified EHR interoperability |
| Da Vinci IGs | CMS payer-to-payer and prior auth exchange |
| CDS Hooks | Real-time clinical decision support in EHR workflows |
| Bulk Data ($export) | Population health and payer analytics |
Where HL7 v2 and FHIR share common ground
Despite their architectural differences, both standards solve the same fundamental problem: moving clinical and administrative data reliably between systems. That shared purpose means they overlap significantly in the data domains they cover and the operational priorities they address.
- Reliability and acknowledgment semantics: — HL7 v2 uses MSH-15/16-driven ACK/NACK for message-level acknowledgment; FHIR REST uses HTTP status codes (200, 201, 400, 422) and OperationOutcome resources. The underlying need, confirming that a message was received and processed, is identical. Your testing and monitoring strategy must account for both.
The NIH/NIBIB RADx MARS documentation illustrates this overlap well in diagnostic and public-health contexts, where both formats are used for lab result reporting depending on the receiving system's capabilities.
What are the technical differences that affect your mappings?
This is where the FHIR vs HL7 v2 comparison gets operationally consequential. The architectural gap between flat pipe-delimited segments and a linked resource graph creates a class of mapping problems that no tooling fully automates away.
Data model: flat segments vs. resource graph
An HL7 v2 message is a self-contained document. All context (patient, order, result, provider) lives in segments within a single message. A FHIR transaction, by contrast, distributes that context across linked resources: a DiagnosticReport references an Observation, which references a Patient, which references a Practitioner. When you translate an ORU^R01 to FHIR, you must either resolve those references to existing resources on the server or create them as part of a Bundle transaction. That referential model is more powerful for querying but requires more state management during ingestion.
Cardinality mismatches and nullFlavor handling
Cardinality is the most common source of silent data loss in v2-to-FHIR translations. HL7 v2 allows many fields to repeat (OBX-5 can carry multiple values in some implementations), while a target FHIR profile may constrain the same attribute to 0..1. The HL7 v2→FHIR mapping guidelines address this directly: when a v2 field repeats and the FHIR target is singular, you must define a canonicalization rule (take the first value, concatenate, or split into multiple Observation instances). There is no universal answer; the rule must be documented per interface.
NullFlavor handling is the companion problem. HL7 v2 uses specific values (like "" for not applicable or coded values like UNK) to signal missing or unknown data. FHIR uses the dataAbsentReason extension for required fields that have no value. Mapping these correctly requires explicit rules in your integration engine, not just field-level mapping.
Datatype and timestamp conversions
v2 DTM format (YYYYMMDDHHMMSS±ZZZZ) must convert to ISO 8601 (YYYY-MM-DDTHH:MM:SS+HH:MM) for FHIR dateTime, date, or instant types. Partial dates (v2 allows YYYYMM or YYYY) require special handling because FHIR's date type accepts partial dates but instant does not. Coded elements in v2 carry the code, description, and coding system in a CWE or CE datatype; FHIR's CodeableConcept carries a coding array with system, code, and display, plus a text field. The mapping is conceptually straightforward but requires consistent system URI resolution (e.g., http://loinc.org for LOINC codes).
Transport and security
MLLP runs over raw TCP, typically on port 2575, and relies on network-layer controls (VPN, firewall rules, TLS wrappers) for security. FHIR REST runs over HTTPS with TLS 1.2 or 1.3 required, and SMART on FHIR adds OAuth2 for application-level authorization. If your current v2 infrastructure uses MLLP without TLS, that gap must be addressed before any FHIR-adjacent work, because the FHIR transport model assumes HTTPS as the baseline.
Vocabulary alignment
Local code tables in v2 (HL7 user-defined tables, site-specific codes) do not translate automatically to FHIR CodeableConcepts backed by canonical systems. A lab that reports results using internal result codes must build a terminology mapping table before those results can populate FHIR Observation resources with valid LOINC codes. This is often the longest-lead-time item in a migration project.
Pro Tip: Run a vocabulary audit on your v2 OBX-3 codes before scoping any migration timeline. The ratio of LOINC-coded to locally-coded observations in your ORU feed is the single best predictor of terminology alignment effort.
Concrete mapping examples: lab results, medication orders, and ADT flows
The HL7 v2→FHIR Implementation Guide provides structured segment maps for the most common message types. The patterns below are derived from those maps and reflect the decisions your team will face on every interface.
Lab result: ORU^R01 → DiagnosticReport + Observation
MSH→MessageHeader(sender, receiver, event code)PID-3(patient identifier list) →Patient.identifier(resolve or create Patient resource; assigning authority →systemURI)OBR-4(universal service identifier, LOINC preferred) →DiagnosticReport.codeOBR-7(observation date/time) →DiagnosticReport.effectiveDateTime(convert DTM → ISO 8601)OBX-3(observation identifier) →Observation.code(validate against LOINC; map local codes via terminology service)OBX-5(observation value) →Observation.value[x](type depends on OBX-2: NM →valueQuantity, ST →valueString, CWE →valueCodeableConcept)OBX-6(units) →Observation.valueQuantity.unit+.system(UCUM URI)OBX-7(reference range) →Observation.referenceRangeOBX-8(abnormal flags) →Observation.interpretationOBX-11(observation result status) →Observation.status(F → "final", P → "preliminary", C → "corrected")
Cardinality callout: If a single OBR has multiple OBX segments (the norm for panel results), each OBX becomes a separate Observation resource, all referenced from a single DiagnosticReport. Your integration engine must group OBX segments by OBR and generate the DiagnosticReport-to-Observation reference links correctly.
Medication order: ORM^O01 → ServiceRequest / MedicationRequest
ORC-2(placer order number) →ServiceRequest.identifier(type: PLAC)ORC-3(filler order number) →ServiceRequest.identifier(type: FILL)ORC-9(date/time of transaction) →ServiceRequest.authoredOnORC-12(ordering provider) →ServiceRequest.requester(resolve to Practitioner resource)RXO-1(requested give code, RxNorm preferred) →MedicationRequest.medication[x]RXO-2/RXO-3(dose, units) →MedicationRequest.dosageInstruction
Extensions are typically required for site-specific fields in ZRX or ZPI segments that carry local order attributes with no FHIR base equivalent.
ADT flow: ADT^A01 → Encounter + Patient
PID-5(patient name) →Patient.name(family, given, prefix; v2 XPN → FHIR HumanName)PID-7(date of birth) →Patient.birthDate(DTM → date, partial date handling required)PID-8(administrative sex) →Patient.gender(v2 table 0001 → FHIR AdministrativeGender value set; "U" → "unknown")PV1-2(patient class) →Encounter.class(I/O/E/P → inpatient/outpatient/emergency/pre-admission)PV1-3(assigned patient location) →Encounter.locationPV1-7(attending doctor) →Encounter.participantPV1-44(admit date/time) →Encounter.period.startPV1-45(discharge date/time) →Encounter.period.end
Pro Tip: Build round-trip validation tests for every mapping pattern: send a known v2 message through your translation layer, convert to FHIR, then reverse-translate back to v2 and diff against the original. Discrepancies in that diff are your data loss inventory before go-live.
How to plan and run an HL7 v2 to FHIR migration
The most common failure mode in migration projects is treating the HL7 v2 to FHIR mapping as a one-time technical task rather than a phased program with governance. Practitioner guidance consistently recommends interface-by-interface analysis over a "lift and shift" approach, and the evidence supports that recommendation: v2 will remain in production for many years while FHIR grows for new APIs.
Discovery checklist
Before writing a single mapping rule, inventory your environment:
- List every active interface: message type, version, sending system, receiving system, owner, and daily volume.
- Document downstream consumers for each feed (who breaks if this interface changes?).
- Identify which interfaces carry data subject to ONC/CMS mandates (patient access, payer exchange).
- Flag interfaces with heavy Z-segment usage or local code tables — these carry the highest mapping complexity.
- Confirm trading partner FHIR capability: does the peer system have a FHIR R4 endpoint, and which profiles does it support?
Prioritization rules
Not every interface needs to migrate on the same timeline. Apply these rules to sequence your work:
- Low-risk candidates: — Simple, low-volume feeds with no Z-segments and LOINC-coded observations are good early wins for building team confidence.
Step-by-step migration checklist
- Map: — Use the HL7 v2→FHIR IG segment maps as your baseline. Document every field-level decision, including cardinality rules and nullFlavor handling.
- Terminology alignment: — Build or acquire a terminology service. Map local code tables to LOINC, SNOMED CT, or RxNorm. Document unmapped codes and the fallback strategy (text-only CodeableConcept).
Testing with synthetic data is non-negotiable. Real patient data in a test environment creates HIPAA exposure; synthetic data generated to match your production message profiles gives you coverage without the risk. Replay testing (feeding historical production messages through the new translation layer) is the most effective way to surface edge cases before they affect live care.
The HL7 v2→FHIR mapping guidelines document is the authoritative reference for the decisions in steps 1 and 2. Treat it as a starting point, not a complete specification — every production interface will require local profiling decisions that the IG cannot anticipate.
When should you choose FHIR, keep HL7 v2, or build a hybrid?
The answer is rarely binary. Use this checklist at interface intake to categorize each integration as "migrate now," "defer," or "keep with translation layer."
Choose FHIR when:
- The use case is mandated by ONC/CMS (patient access API, payer-to-payer exchange, prior authorization).
- The consuming application is a patient-facing portal, mobile app, or third-party analytics tool that expects REST/JSON.
- You need query-based access (pull by patient, date range, or code) rather than push-only event delivery.
- The trading partner has a certified FHIR R4 endpoint and supports relevant US Core or Da Vinci profiles.
- The interface is new (greenfield) with no legacy system constraints.
Keep HL7 v2 when:
- The interface is high-volume (thousands of messages per minute) and latency-sensitive, where MLLP's lower overhead is operationally significant.
- Both endpoints are legacy systems with no FHIR capability and no regulatory mandate to change.
- The interface is stable, low-maintenance, and carries no data subject to patient access mandates.
- Device-level constraints (medical devices, point-of-care instruments) make v2 the only practical option.
Build a hybrid (translation layer) when:
- A downstream FHIR consumer needs data that originates in a v2 system with no FHIR capability.
- You are migrating incrementally and need both formats in parallel during a transition window.
- Your internal canonical model aggregates data from multiple v2 sources for FHIR-based reporting or analytics.
Governance for mixed environments
Operating both standards sustainably requires organizational discipline beyond the technical layer. Define a canonical internal data model that sits above both wire formats; your integration engine translates in and out of that model rather than building point-to-point v2-to-FHIR mappings for every interface pair. Maintain a profile registry so every team knows which FHIR profiles and v2 message specifications are in use. Instrument every translation with structured logging so you can trace a message from its v2 origin through transformation to its FHIR destination. Industry practitioners consistently identify the canonical internal model as the architectural decision that most reduces long-term maintenance cost in mixed-standard environments.
How does a modern PGx platform integrate HL7 v2 and FHIR?
Pharmacogenomics reporting is a concrete example of a clinical workflow that must operate in both worlds simultaneously. A laboratory receives orders and patient demographics via HL7 v2 from a hospital LIS or EHR, performs genotyping, and then needs to deliver structured PGx reports back to the ordering clinician through a FHIR-native EHR interface, a patient portal, or a CDS Hooks integration. That inbound-v2 / outbound-FHIR architecture is exactly what Signalpgx is built around.
Signalpgx integration architecture
Signalpgx operates a dual-ingestion pipeline: a v2 listener accepts ORU and ORM messages from laboratory instruments and LIS systems over MLLP, while a FHIR API endpoint accepts DiagnosticReport and Observation resources from FHIR-capable senders. Both paths normalize to a canonical internal model that carries genotype data, medication history, and clinical context. From that canonical model, the platform generates physician-reviewed PGx reports and exposes results as FHIR DiagnosticReport resources and CDS Hooks cards for real-time EHR integration.
The EHR integration via FHIR and CDS Hooks pattern Signalpgx uses means that a clinician opening a patient chart in a FHIR-enabled EHR can receive a PGx-informed medication alert without leaving the prescribing workflow. That integration requires the platform to maintain a FHIR R4 endpoint, support SMART on FHIR for authorization, and respond to CDS Hooks order-select and patient-chart-opened events within the latency window the EHR expects.
Key Takeaways
FHIR is the required standard for new patient and payer APIs under ONC/CMS mandates, while HL7 v2 remains the practical choice for high-volume internal event feeds — and most organizations will operate both for years, connected through a well-governed integration engine.
| Point | Details |
|---|---|
| FHIR for new APIs | Choose FHIR R4 for any interface subject to ONC/CMS patient access or payer exchange mandates. |
| Keep v2 for event feeds | High-volume, low-latency internal feeds (ADT, ORU, ORM) are stable on HL7 v2 and do not require migration unless mandated. |
| Use the HL7 v2→FHIR IG | The official HL7 v2→FHIR Implementation Guide is the authoritative baseline for every mapping project; expect interface-specific profiling on top. |
| Cardinality is your top risk | Mismatched cardinality and nullFlavor handling are the primary sources of silent data loss; validate each interface individually. |
| Signalpgx bridges both worlds | Signalpgx ingests HL7 v2 lab feeds and exposes FHIR R4 APIs and CDS Hooks, letting labs deliver PGx reporting without replacing existing v2 infrastructure. |
The case for governance over tooling in hybrid HL7 environments
The conversation about FHIR vs HL7 v2 in most health IT teams gets stuck on tooling: which interface engine, which validator, which mapping spreadsheet. Those are real decisions, but they are downstream of a more consequential one: whether your organization has a canonical internal model and a governance process that owns it.
Every health system I have seen struggle with long-term interoperability costs shares the same root cause. They built point-to-point translations between v2 and FHIR for each interface independently, without a shared model, without a terminology service, and without centralized monitoring. When a trading partner upgrades their EHR and changes a field, three teams discover the breakage in three different ways, and the fix happens in three different places. The canonical model approach eliminates that fragmentation: one place where v2 maps in, one place where FHIR maps out, and one observability layer that tells you when something breaks before a clinician notices.
For a mid-sized health system running 50–150 active interfaces, a realistic timeline for standing up that architecture, including discovery, canonical model design, integration engine configuration, and the first wave of interface migrations, is 12–18 months with a dedicated team of two to four integration engineers and a clinical informaticist who owns the terminology governance. That timeline assumes you are not starting from zero: you have an existing integration engine (Mirth Connect, Rhapsody, or equivalent) and a FHIR server in your environment. The Saga IT guidance on FHIR vs HL7 decision rules aligns with this framing: the question is not which standard wins, but which standard serves each interface's requirements, governed by a process that keeps the answer current as requirements evolve.

Signalpgx gives labs FHIR-ready PGx reporting without replacing your v2 infrastructure
Labs that need to deliver pharmacogenomics reporting through FHIR-native EHR integrations face a real tension: their existing infrastructure speaks HL7 v2, their ordering clinicians expect CDS Hooks alerts in the EHR, and their patients expect structured reports through a portal. Building that translation layer from scratch, with a canonical model, a terminology service, a FHIR server, and a CDS Hooks endpoint, is a multi-year project for most lab IT teams.
Signalpgx compresses that timeline. The platform's white-label PGx reporting infrastructure accepts your existing v2 ORU and ORM feeds, normalizes genotype and medication data against evidence from 20+ sources including CPIC guidelines and FDA biomarker labeling, and delivers physician-reviewed reports through FHIR R4 APIs and CDS Hooks without requiring you to replace a single piece of your current integration stack. Labs typically can go from signed agreement to live reporting within about a week.

Your team gets a fully audited, HIPAA-compliant integration pipeline with structured logging, role-based access control, and living reanalysis that updates recommendations as clinical guidelines change. Technical leads can review the full white-label PGx reporting platform capabilities and integration specifications, or book a technical demo to walk through your specific v2 message types and FHIR integration requirements with the Signalpgx team.

Authoritative references and implementation resources
The resources below are the primary starting points for any HL7 v2 to FHIR implementation project. Each serves a distinct purpose in the implementation lifecycle.
- Hl7 FHIR
- HL7 Version 2 to FHIR
- HL7 v2 to FHIR mapping guidelines (2024Jan)
- What is FHIR? (HealthIT.gov fact sheet)
- RADx® MARS: HL7v2 vs FHIR
- Reporting laboratory data (CDC)
- FHIR R4 vs Legacy HL7 - First Line Software
- HL7 v2 vs v3 vs FHIR: Complete Comparison for 2026
- HL7 vs FHIR: Differences, Use Cases & When (2026) — Saga IT
