Ask five healthcare engineers which HL7 standard to use and you will hear three different answers. The reason is not that the standards are ambiguous — it is that each one optimizes for a different era, problem, and audience. HL7 v2.x won the 1990s and still moves 85% of real-time clinical traffic in US hospitals. HL7 v3 aimed to replace it, failed commercially but left a durable legacy in CDA. FHIR, introduced in 2011, is the modern standard for REST-based interoperability and is rapidly becoming the required API for patient access, payer-provider data exchange, and third-party app integration.
This article is the pragmatic comparison we use with clients when they ask "which one should we pick?" — with real wire-format examples, actual adoption data, and a frank discussion of why HL7 v3 never gained broad traction.
For wider context, see our healthcare interoperability guide and EHR integration guide.
1. Three Standards, One Problem
All three standards attempt to solve the same problem: how do heterogeneous healthcare systems exchange clinical data reliably? They differ in the era they were built, the wire format they chose, and the assumptions they make about the surrounding ecosystem.
- HL7 v2.x (1989 onward) — pragmatic, minimal, pipe-delimited, TCP/MLLP. Designed by vendors for vendors.
- HL7 v3 (2005) — rigorous, RIM-based, XML. Designed by modellers to fix v2's ambiguity.
- FHIR (2014 DSTU1, 2019 R4, 2023 R5) — modern, REST, JSON/XML. Designed by engineers with web experience.
Each was a response to the shortcomings of the previous generation. HL7 v3 was a reaction to v2's loose optionality. FHIR was a reaction to v3's complexity and to the 2010s explosion of web APIs in other industries. Understanding the lineage helps you predict where each fits best.
2. HL7 v2.x — The De Facto Workhorse
HL7 v2 is the format. When a US hospital says "send an HL7 message" they mean v2. Every major EHR emits it, every interface engine consumes it, and every integrator on your team knows it.
Key characteristics:
- Pipe-delimited, segment-based text format.
- Over 150 message types — ADT, ORM, ORU, SIU, MDM, DFT, VXU are the most common.
- Carried almost exclusively over MLLP/TCP.
- Versions 2.3 through 2.9 are all in production use simultaneously — the protocol has been backward-compatible since v2.3.1.
- Schema loose by design — custom Z-segments are common, and optional fields are often populated in vendor-specific ways.
A sample ADT^A01 (patient admission):
MSH|^~\&|EPIC|UCHEALTH|MIRTH|TACTION|20260421093000||ADT^A01|MSG00001|P|2.5
EVN|A01|20260421093000
PID|1||123456^^^UCHEALTH^MR||DOE^JOHN^Q||19720101|M|||123 MAIN ST^^DENVER^CO^80202
PV1|1|I|2000^2012^01||||0010^ATTEND^ALBERT|||CAR||||ADM|A0For a complete walkthrough of segment structure, see HL7 v2 message structure explained. For specific message types, see ADT messages, ORM/ORU lab workflow, SIU scheduling, MDM documents, DFT billing, and VXU immunization.
3. HL7 v3 and the RIM
HL7 v3 was a ground-up redesign built on the Reference Information Model (RIM) — a UML-style object model of healthcare concepts. Payloads are XML, heavily structured, and governed by strict schemas derived from the RIM.
Key characteristics:
- XML-based with formal XSD schemas.
- Every payload derives from RIM classes: Act, Entity, Role, Participation, ActRelationship, RoleLink.
- Strict datatypes with explicit null semantics (flavours of null).
- Transport agnostic — HTTP, SOAP, file, MLLP.
- Governed by implementation guides ("messages" and "documents" are distinct subsets).
A simplified v3 message (patient admit) fragment:
<PRPA_IN402001 xmlns="urn:hl7-org:v3">
<id root="2.16.840.1.113883.19.5" extension="MSG00001"/>
<creationTime value="20260421093000"/>
<interactionId root="2.16.840.1.113883.1.6" extension="PRPA_IN402001"/>
<processingCode code="P"/>
<processingModeCode code="T"/>
<acceptAckCode code="AL"/>
<receiver typeCode="RCV">
<device classCode="DEV" determinerCode="INSTANCE">
<id root="2.16.840.1.113883.19.5.1"/>
</device>
</receiver>
<sender typeCode="SND">...</sender>
<controlActProcess classCode="CACT" moodCode="EVN">
...
</controlActProcess>
</PRPA_IN402001>The specification is rigorous and the semantics are clean — in theory. In practice, the payloads were large, developer tooling was limited, and implementing v3 cost an order of magnitude more engineering effort than v2. Outside of a handful of government-mandated flows, vendors declined to adopt it at scale.
4. FHIR — Fast Healthcare Interoperability Resources
FHIR took the lessons of v2 (practical, vendor-friendly, incrementally adoptable) and v3 (structured data model, formal semantics) and wrapped them in the conventions of modern web APIs. The result has become the dominant standard for new healthcare APIs in the 2020s.
Key characteristics:
- REST-based: GET, POST, PUT, PATCH, DELETE over HTTPS.
- Resources (Patient, Observation, Encounter, Medication, etc.) with well-defined schemas.
- JSON by default; XML and RDF/Turtle also supported.
- URL-based search:
GET /Patient?identifier=123456&_count=10. - Bundles for collections; references between resources via URLs.
- SMART on FHIR for authorization (OAuth 2.0 with healthcare-specific scopes).
- Subscriptions and operations for real-time event streaming and custom workflows.
A Patient resource in JSON:
{
"resourceType": "Patient",
"id": "123456",
"identifier": [{
"system": "urn:oid:2.16.840.1.113883.19.5",
"value": "123456"
}],
"name": [{
"family": "Doe",
"given": ["John", "Q"]
}],
"gender": "male",
"birthDate": "1972-01-01",
"address": [{
"line": ["123 Main St"],
"city": "Denver",
"state": "CO",
"postalCode": "80202"
}]
}For a hands-on FHIR walkthrough including search, OAuth, and bulk export, see our FHIR integration guide.
5. Wire Formats Side-by-Side
Patient demographics in each format:
5.1 HL7 v2
PID|1||123456^^^UCHEALTH^MR||DOE^JOHN^Q||19720101|M|||123 MAIN ST^^DENVER^CO^802025.2 HL7 v3 (RIM-based)
<patient classCode="PAT">
<id root="2.16.840.1.113883.19.5" extension="123456"/>
<statusCode code="active"/>
<patientPerson classCode="PSN" determinerCode="INSTANCE">
<name>
<given>John</given>
<given qualifier="MID">Q</given>
<family>Doe</family>
</name>
<administrativeGenderCode code="M" codeSystem="2.16.840.1.113883.5.1"/>
<birthTime value="19720101"/>
<addr use="H">
<streetAddressLine>123 Main St</streetAddressLine>
<city>Denver</city>
<state>CO</state>
<postalCode>80202</postalCode>
</addr>
</patientPerson>
</patient>5.3 FHIR (JSON)
{
"resourceType": "Patient",
"identifier": [{"system": "urn:oid:2.16.840.1.113883.19.5", "value": "123456"}],
"name": [{"family": "Doe", "given": ["John", "Q"]}],
"gender": "male",
"birthDate": "1972-01-01",
"address": [{
"use": "home",
"line": ["123 Main St"],
"city": "Denver", "state": "CO", "postalCode": "80202"
}]
}Same information in each — roughly 110 bytes for v2, 650 for v3, 310 for FHIR JSON. Verbosity alone is not a reason to pick one over another, but for high-volume feeds it matters.
6. Feature Comparison Table
| Feature | HL7 v2.x | HL7 v3 | FHIR |
|---|---|---|---|
| Launched | 1989 | 2005 | 2014 |
| Wire format | Pipe-delimited text | XML (RIM-based) | JSON / XML / RDF |
| Transport | MLLP / TCP | HTTP, SOAP, file, MLLP | HTTPS REST |
| Paradigm | Message / event | Message & document | Resource REST |
| Schema rigor | Loose | Very strict | Moderate with profiles |
| Learning curve | Medium | High | Low-medium |
| Tooling | Mature, ubiquitous | Limited | Rapidly growing |
| Adoption (US 2026) | ~85% of real-time feeds | Niche + CDA | All new APIs |
| Mandated by | Clinical workflows | C-CDA for MU | ONC, CMS rules |
| Security | MLLPS (bolt-on TLS) | HTTPS / WS-Security | OAuth 2.0 / SMART |
| Search & query | Not in spec | Limited | Core feature |
| Versioning | Backwards compatible since 2.3 | Rigid | R4, R4B, R5 |
| Future trajectory | Stable legacy | Fading (ex-CDA) | Growing |
7. Adoption and Ecosystem
Rough US adoption picture in 2026:
- HL7 v2.x — every hospital EHR, every LIS, every RIS, every pharmacy system. Interfaces measured in the tens of thousands of production feeds nationwide.
- HL7 v3 — mostly CDA-derived: C-CDA for summary-of-care, Public Health Case Reporting, some national registries. Non-CDA v3 is rare.
- FHIR — patient access APIs mandated by ONC 21st Century Cures / CMS Interoperability Rules, payer-provider data exchange, third-party apps via SMART on FHIR, USCDI data classes, most greenfield integrations.
The trend is unambiguous: HL7 v2 remains massive but stable; FHIR is the growth vector. Most US integration teams now operate both standards simultaneously and use their interface engine to translate between them.
8. Tooling Landscape
8.1 HL7 v2 tooling
- Interface engines: Mirth Connect, Rhapsody, Cloverleaf, Iguana, InterSystems Ensemble.
- Testing tools: HL7Soup, 7Edit, HAPI TestPanel, custom Python / Java tooling.
- Parsers: HAPI (Java), python-hl7, hl7apy, Ruby ruby-hl7.
8.2 HL7 v3 tooling
- Limited — most interface engines can parse v3 XML but have few v3-specific features.
- CDA tooling: model.mdht, HAPI CDA, various validators for C-CDA 2.1.
- Most engineers encounter v3 only via C-CDA; pure v3 messaging is rare.
8.3 FHIR tooling
- Servers: HAPI FHIR, Microsoft FHIR Server, Firely, Medplum, Aidbox, Google Cloud Healthcare API.
- Client libraries: fhir.resources (Python), fhir-client-js, .NET Firely, Java HAPI FHIR.
- Validators: HL7 FHIR Validator, HAPI FHIR Validator, Firely Terminal.
- Sandboxes: SMART App Launcher, Epic / Cerner developer portals.
9. Why v3 Largely Failed
HL7 v3 is a cautionary tale for every standards body. It was designed by committee with admirable intentions — formal semantics, unambiguous RIM-based data model, consistent datatype rules — and it crashed into the rocks of vendor reality.
- Payload size — a v3 patient admission could be 5–10× the size of the equivalent v2 message. For real-time clinical feeds, that was unacceptable.
- Cognitive load — the RIM is elegant but steep. Engineers who had shipped v2 for years found v3 alien.
- Tooling vacuum — few libraries, few testing tools, few vendors supporting both sides of an interface.
- Lack of ROI — vendors saw no compelling commercial reason to switch. Customers weren't asking for it.
- Backward compatibility loss — v3 was a clean break, forcing every system on both sides of an interface to upgrade in lockstep.
FHIR learned every lesson. It kept the useful data model ideas of v3, dropped the XML-only dogma, adopted web conventions, prioritized tooling, and allowed incremental adoption. The result is the standard that actually replaced v2 for new work.
10. Migration Paths and Bridging
10.1 HL7 v2 to FHIR
The HL7 v2-to-FHIR project at HL7 International publishes canonical mappings. Most interface engines ship production-ready bridges.
// Mirth Connect — convert ADT^A01 to FHIR Patient + Encounter
// Source: MLLP Listener receives v2
// Destination 1: HTTP Sender POSTs FHIR Patient to FHIR server
// Destination 2: HTTP Sender POSTs FHIR Encounter referencing Patient
var pid = msg['PID'];
var patient = {
resourceType: 'Patient',
identifier: [{
system: 'urn:oid:2.16.840.1.113883.19.5',
value: pid['PID.3']['PID.3.1'].toString()
}],
name: [{
family: pid['PID.5']['PID.5.1'].toString(),
given: [pid['PID.5']['PID.5.2'].toString()]
}],
gender: mapGender(pid['PID.8']['PID.8.1'].toString()),
birthDate: formatDate(pid['PID.7']['PID.7.1'].toString())
};
channelMap.put('patientResource', JSON.stringify(patient));10.2 FHIR to HL7 v2
The reverse direction is common when modern applications (patient portals, third-party apps) need to update legacy systems that speak only v2. Interface engines consume FHIR over REST and emit v2 over MLLP.
10.3 Bridging via canonical model
Mature teams don't translate v2 ↔ FHIR directly for every interface. Instead they project every inbound format into an internal canonical model and translate out. This halves the number of mappings for N interfaces and prevents translation drift.
10.4 When to skip migration
Not every v2 interface needs to become FHIR. Real-time clinical event streams (ADT, ORU) work well on v2/MLLP. Migrate when an interface serves a use case FHIR does better — patient access, query-based retrieval, bulk export.
11. When to Pick Each
11.1 Pick HL7 v2 when
- The peer system requires it — this is still the default for hospital EHR integrations.
- You need real-time event streams: ADT admits/discharges, ORU lab results, ORM orders, SIU scheduling.
- You are integrating with a vendor whose FHIR support is immature or read-only.
- Latency budgets are tight and payload size matters.
11.2 Pick FHIR when
- You are building a new API — patient access, payer-provider, third-party app.
- You need query / search capability (find a patient by name, list observations by date).
- Federal rules require it — ONC 21st Century Cures, CMS Interoperability Rule.
- You are integrating cloud services that expose FHIR natively.
11.3 Pick HL7 v3 when
- You must exchange C-CDA documents for Meaningful Use / Promoting Interoperability.
- A specific public-health or registry integration requires it.
- Otherwise: don't start new v3 work.
In practice most teams run v2 and FHIR side-by-side, with an interface engine (Mirth Connect is our canonical choice) bridging between them. See our Mirth Connect complete guide for the full architecture pattern and Mirth helpdesk if you need production support today.
12. Frequently Asked Questions
What is the difference between HL7 v2 and FHIR?
HL7 v2 is a pipe-delimited, segment-based messaging format carried over MLLP/TCP, designed in the late 1980s for async event messaging inside hospitals. FHIR is a modern REST API standard with JSON/XML/RDF payloads, a resource-oriented data model, and built-in support for search, paging, and subscription. They solve overlapping but distinct problems.
Is HL7 v3 still used?
Very little in the United States. HL7 v3 lives on in specific public-health and registry integrations, and CDA (Clinical Document Architecture) — which is an HL7 v3 derivative — is widely used for C-CDA exchange. Greenfield projects in 2026 choose FHIR or stay on HL7 v2.
Does FHIR replace HL7 v2?
Not immediately and not entirely. FHIR is the direction of travel for new APIs, patient access, and payer-provider workflows; HL7 v2 remains the dominant transport for real-time clinical event streams (ADT, ORU, ORM, SIU) for at least another decade. Most production environments run both.
Why did HL7 v3 fail to gain broad adoption?
It was too heavy. The RIM-based design was academically rigorous but the XML payloads were large, the schema was hard to implement, and vendors could not justify the engineering cost versus HL7 v2's simplicity. FHIR was built explicitly to avoid v3's mistakes.
What wire format does FHIR use?
FHIR payloads are carried as JSON (default), XML, or RDF/Turtle, exchanged over HTTPS using standard REST verbs (GET, POST, PUT, PATCH, DELETE). Search is URL-based; updates are idempotent; authentication typically uses OAuth 2.0 / SMART on FHIR.
Can I transform HL7 v2 messages into FHIR resources?
Yes — Mirth Connect, Rhapsody, Cloverleaf, and InterSystems all ship HL7 v2 to FHIR transformation packages or libraries. The HL7 v2-to-FHIR project at HL7 International publishes canonical mappings you can reuse.
Which standard should I use for a greenfield integration today?
Look at the other side. If the peer speaks HL7 v2, you speak HL7 v2 — that is still the reality for most real-time clinical messaging. If the peer exposes a FHIR API, use FHIR. Never build v3 from scratch.
What about C-CDA?
C-CDA (Consolidated Clinical Document Architecture) is based on HL7 v3 and is widely used for summary-of-care documents, particularly in Meaningful Use / Promoting Interoperability flows. FHIR Composition resources and Bundles are the modern equivalent and will gradually displace C-CDA over the next several years.
Is FHIR secure by default?
FHIR inherits TLS from HTTPS and SMART on FHIR from OAuth 2.0, both of which are well understood. It is more secure by default than legacy MLLP deployments, provided implementers enable TLS, validate scopes, and rotate credentials properly.
Do I need to pick one standard across my whole organization?
No, and most don't. Modern integration engines (Mirth Connect included) bridge HL7 v2, FHIR, and even legacy v3 / C-CDA in the same workflow. Pick the right standard per interface, and keep a consistent internal canonical model to avoid translation sprawl.
Related Reading
- HL7 Integration: The Complete Guide
- FHIR Integration: The Complete Guide
- Healthcare Interoperability Guide
- EHR Integration Guide
- HL7 v2 Message Structure Explained
- MLLP Protocol Explained
- HL7 ACK/NAK Explained
- HL7 ADT Messages Reference
- HL7 ORM / ORU Lab Workflow
- Common HL7 Integration Errors
- Mirth Connect: The Complete Guide