Ovok blog

FHIR vs HL7 v2: Differences, Examples and Migration

FHIR vs HL7 v2: messages vs resources, transport, tooling, when v2 still wins, v2-to-FHIR mapping and the same lab result shown in both formats.

FHIR vs HL7 v2 comes down to two different designs for the same job. HL7 v2 is an event-driven messaging standard: systems push pipe-delimited messages to each other when something happens. FHIR is a resource-based standard: data lives at URLs and clients read, write and search it over a REST API with JSON. Most hospitals still run on v2 internally, while new apps, patient access and cross-organisation exchange are moving to FHIR, so in practice you will often need both.

Key takeaways

  • HL7 v2 sends messages (ADT, ORM, ORU) when events occur; FHIR exposes resources (Patient, Observation) that you query when you need them.
  • v2 typically travels over MLLP on a TCP socket inside the hospital network; FHIR uses HTTPS, JSON and OAuth 2.0.
  • v2 is still the backbone of in-hospital interfaces and is unlikely to disappear soon. Do not plan a "big bang" replacement.
  • The HL7 v2-to-FHIR implementation guide (STU1, published October 2025) gives official mappings from v2 segments and data types to FHIR resources.
  • The common pattern is coexistence: an integration layer translates v2 feeds into FHIR resources for apps and analytics.
  • CDA is a third HL7 family, for clinical documents, and FHIR also covers that use case through Composition and document Bundles.

A short history

HL7 International was founded in 1987, and Version 2 grew out of that early work on exchanging data with hospital information systems. Over the following decades the 2.x family (2.1 through 2.5.1 and later releases) became the default way lab systems, admission systems, radiology and billing talk to each other inside a hospital. Each release is largely backward compatible, which is one reason v2 has lasted so long.

HL7 tried a clean-slate successor with Version 3 and its Reference Information Model. V3 messaging saw limited uptake, but one V3-based product, the Clinical Document Architecture (CDA), became widely used for clinical documents such as discharge summaries.

FHIR started as a fresh approach in the early 2010s. The first draft standard for trial use appeared in September 2014, R4 followed in December 2018 with the first normative content, and R5 was published in March 2023. If you are new to FHIR itself, start with our developer guide: What is FHIR?

Message model vs resource model

This is the real difference, and everything else follows from it.

HL7 v2: messages about events

A v2 message announces that something happened. The trigger event is encoded in the message type:

  • ADT^A01 — a patient was admitted.
  • ADT^A08 — patient information was updated.
  • ORM^O01 or OML^O21 — an order was placed.
  • ORU^R01 — results are available.

Each message is made of segments (MSH header, PID patient, PV1 visit, OBR order, OBX observation), each segment of fields separated by |, and each field of components separated by ^. The receiving system parses the message, updates its own database and replies with an acknowledgement (ACK). There is no shared "current state" you can query; each system keeps its own copy, built from the stream of messages it has received.

FHIR: resources with URLs

FHIR gives each piece of data an identity: Patient/123, Observation/456. A client can read the current state at any time, search across resources and update them. Events still exist (Subscriptions notify clients about changes, and FHIR has a messaging paradigm too), but the default interaction is request and response against resources.

That shift has practical effects:

  • Querying. With FHIR you can ask "all glucose results for this patient in the last 30 days" in one call. With v2 you either stored every ORU yourself or you send a query message, which few systems support well.
  • Consistency. FHIR resources have versions and a history. v2 receivers must process messages in order, and a missed message means silent drift.
  • Granularity. One v2 ORU can carry a patient, an order and many results. In FHIR those are separate Patient, ServiceRequest, DiagnosticReport and Observation resources linked by references.

Transport and encoding

  • HL7 v2 is usually encoded in "ER7" pipe-and-hat format (an XML encoding exists but is less common) and sent over MLLP, a minimal framing protocol on top of a raw TCP connection. Security has traditionally relied on the network: VPNs, private lines, firewalls. There is no standard authentication inside the protocol.
  • FHIR uses HTTPS, JSON (or XML), standard HTTP status codes and OAuth 2.0. SMART App Launch standardises authorization scopes and app launch. This is what makes FHIR usable from the public internet, mobile apps and cloud services.

Tooling and developer experience

v2 tooling centres on interface engines: products that receive, route, transform and deliver messages, often configured by specialised integration analysts. Every site has its own variations ("Z-segments", local code tables, optional fields used in non-standard ways), so each new interface is partly a custom project.

FHIR tooling looks like the rest of modern software: HTTP clients, OpenAPI-style references, open-source servers and validators, SDKs in many languages, JSON schemas and conformance testing against published profiles. A developer who knows REST can be productive quickly. The flip side: FHIR's flexibility means you still need profiles to agree on details, and FHIR servers vary in which search parameters and operations they support. Always read the server's CapabilityStatement; our FHIR API and search guide shows how.

The same lab result in HL7 v2 and FHIR

Here is one fictional fasting glucose result, 95 mg/dL, reported as final. First as an HL7 v2.5.1 ORU^R01 message (one segment per line):

  • MSH|^~\&|LAB|HOSP|EHR|HOSP|20261016083000||ORU^R01^ORU_R01|MSG00001|P|2.5.1
  • PID|1||PAT-EXAMPLE-001^^^HOSP^MR||Mustermann^Johann||19700101|M
  • OBR|1||LAB-12345|2345-7^Glucose [Mass/volume] in Serum or Plasma^LN|||20261016070000
  • OBX|1|NM|2345-7^Glucose [Mass/volume] in Serum or Plasma^LN||95|mg/dL^^UCUM|70-99|N|||F

Reading the OBX segment field by field: OBX-2 NM says the value is numeric, OBX-3 is the LOINC code, OBX-5 is the value, OBX-6 the unit, OBX-7 the reference range, OBX-8 N the normal flag and OBX-11 F the final status. You need the specification (or a lot of experience) to know which position means what.

Now the same result as a minimal FHIR R4 Observation, element by element:

  • "resourceType": "Observation"
  • "status": "final"
  • "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "laboratory"}]}]
  • "code": {"coding": [{"system": "http://loinc.org", "code": "2345-7", "display": "Glucose [Mass/volume] in Serum or Plasma"}]}
  • "subject": {"reference": "Patient/pat-example-001"}
  • "effectiveDateTime": "2026-10-16T07:00:00+02:00"
  • "valueQuantity": {"value": 95, "unit": "mg/dL", "system": "http://unitsofmeasure.org", "code": "mg/dL"}
  • "interpretation": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation", "code": "N"}]}]
  • "referenceRange": [{"low": {"value": 70, "unit": "mg/dL", "system": "http://unitsofmeasure.org", "code": "mg/dL"}, "high": {"value": 99, "unit": "mg/dL", "system": "http://unitsofmeasure.org", "code": "mg/dL"}}]

What changed:

  • Field positions became named elements. status, code and valueQuantity are self-describing.
  • The patient is a reference to a Patient resource, not a copy of demographics inside every message.
  • Code systems are explicit URIs (http://loinc.org, http://unitsofmeasure.org) instead of short labels like LN.
  • The timestamp carries a time zone. The v2 example has none, a frequent source of mapping bugs.
  • The order (OBR) maps to a ServiceRequest and, typically, a DiagnosticReport that groups the Observations. They are left out here to keep the example minimal.

Once stored, the Observation can be fetched with a simple search such as GET [base]/Observation?patient=pat-example-001&code=http://loinc.org|2345-7.

When HL7 v2 still wins

Be honest about where v2 is the right tool:

  • Inside the hospital. Existing lab, radiology and admission systems speak v2, interface engines are already in place, and staff know them. Replacing a working interface brings risk without clinical benefit.
  • High-volume event feeds. ADT and results feeds are a natural fit for push messaging; every downstream system gets every event in order.
  • Vendor reality. If the system you integrate with only offers v2, your choice is made. Many still do.
  • Low latency on a private network. A persistent MLLP connection inside a data centre is simple and fast.

FHIR wins when data must cross organisational boundaries, reach mobile and web apps, be queried on demand, or be secured with modern identity. It is also the direction regulation is heading, including patient-access rules in the US and the European Health Data Space in the EU.

Migration and coexistence patterns

You will rarely "migrate" from v2 to FHIR in one step. These patterns work in practice:

  1. v2-to-FHIR façade. An interface engine or integration service consumes v2 feeds and writes FHIR resources to a FHIR server. Apps read FHIR; hospital systems keep sending v2.
  2. Use the official mappings. The HL7 Version 2 to FHIR implementation guide (STU1, version 1.0.0, published October 2025) provides ConceptMaps from v2 messages, segments, data types and vocabulary to FHIR R4 resources. Start from these instead of inventing your own mapping tables.
  3. Bidirectional bridge for orders. When your app creates orders that must reach a v2 system, write a ServiceRequest in FHIR and let the integration layer emit the matching v2 order message, then map the v2 results back.
  4. New workflows FHIR-first. Remote monitoring, patient apps and questionnaires usually have no v2 history. Build them natively on FHIR and only bridge where a hospital system needs the data.
  5. Identifier discipline. Carry v2 identifiers (MRN from PID-3, order numbers from OBR) into FHIR identifier elements with clear system URIs, so records can be matched in both directions.

Where does CDA fit?

CDA (Clinical Document Architecture) is HL7's XML standard for clinical documents: signed, human-readable documents with structured sections. It remains common for discharge summaries and referral letters, and in the US through C-CDA. FHIR covers the same need with a Composition resource packaged in a document Bundle, which is how the International Patient Summary and the HL7 Europe Patient Summary guides are built. Expect CDA and FHIR documents to coexist for years, just like v2 and FHIR messages.

What this means for a digital-health product

If you are building a remote-monitoring app, a patient portal or a clinician dashboard, design your data model in FHIR from the start, and treat v2 as an integration concern at the hospital boundary. Your own backend should not speak MLLP to mobile phones.

A FHIR backend such as Ovok gives you a FHIR R4 REST and GraphQL API, Access Policies for multi-tenant projects and SDKs for React and React Native, so your team spends its time on the product, not on parsing segments. See how it fits remote patient monitoring, compare options in our RPM platform overview, and check pricing.

FAQ

Is FHIR replacing HL7 v2?

Gradually, and not everywhere. FHIR is the default for new APIs, apps and cross-organisation exchange. v2 remains the backbone of in-hospital interfaces and will coexist with FHIR for many years.

Is FHIR part of HL7?

Yes. FHIR is published by HL7 International, the same organisation behind v2, v3 and CDA. "FHIR vs HL7" really means FHIR vs the older HL7 v2 standard.

Can I convert HL7 v2 messages to FHIR automatically?

Partly. The HL7 v2-to-FHIR implementation guide defines standard mappings, and interface engines can apply them. Local customisations such as Z-segments and site-specific code tables still need manual mapping and testing.

Which is faster, HL7 v2 or FHIR?

For a stream of events on a private network, v2 over MLLP is lean. For reading exactly the data you need on demand, FHIR is usually more efficient because you query instead of storing every message. Performance depends far more on the implementation than on the standard.

Do I need HL7 v2 for a remote patient monitoring app?

Usually not for the app itself. You may need a v2 interface if a hospital customer wants results pushed into its existing systems. Keep that at the integration boundary.

What is MLLP?

The Minimal Lower Layer Protocol, a simple framing scheme that wraps each v2 message with start and end bytes on a TCP connection. It provides no encryption or authentication on its own.

Conclusion

HL7 v2 and FHIR solve interoperability at different layers and in different eras. v2 is the proven, message-driven workhorse inside hospitals; FHIR is the queryable, web-native standard for apps and cross-organisation exchange. Build new products on FHIR, bridge to v2 where hospitals need it, and lean on the official mappings. To try a FHIR R4 API today, open a free project in the Ovok Developer sandbox and follow the Ovok docs, starting with FHIR Basics. Startups can also look at the Ovok offer for startups.

Keep reading