The vocabulary of healthcare integration, defined directly - what HL7 v2 is, what FHIR is, what MLLP is, how they relate and what each looks like in Python.
# -*- coding: utf-8 -*-
# Zato
from zato.hl7v2 import parse_hl7
from zato.server.service import Service
class BothWorlds(Service):
name = 'demo.glossary.both-worlds'
def handle(self) -> 'None':
# HL7 v2 - pipe-delimited segments
msg = self.request.input
family_name = msg.pid.patient_name.family_name
# FHIR - JSON resources over REST
client = self.fhir['FHIR.Sample']
patient = client.resources('Patient').search(
family = family_name,
).first()
self.logger.info('Found %s', patient['id'])
HL7 v2 is the messaging standard hospital systems have exchanged clinical events in since 1987 - a patient is admitted, a lab result is ready, an order is placed, and a message goes out. Messages are plain text in the ER7 encoding - segments separated by carriage returns, fields separated by pipes - a format that has remained stable across versions.
Each line is a segment - MSH is the header, PID the patient, PV1 the visit, OBX a result - and each segment is a sequence of fields with positions defined by the standard. Message types like ADT^A01 (admission) or ORU^R01 (results) say which segments to expect.
MSH|^~\&|SENDER|FACILITY|RECEIVER|FAC|20260315||ADT^A01^ADT_A01|CTL001|P|2.9
EVN|A01|20260315
PID|1||12345^^^HOSP^MR||SMITH^JOHN^A||19800115|M
PV1|1|I|WARD^101^BED1In Python, parse_hl7(raw) turns that text into a typed object where message.pid.patient_name.family_name is 'SMITH' - the receiving HL7 v2 guide shows the full flow.
FHIR - Fast Healthcare Interoperability Resources - is the modern HL7 standard, built on REST and JSON instead of custom encodings. Data is modeled as resources - Patient, Observation, Encounter, MedicationRequest - each a JSON document with a defined structure, exchanged over regular HTTP with searches, reads and writes.
FHIR R4, released in 2019, is the most widely deployed version in production - US and European regulation references it, EHR vendors expose it and the national programs described across this site build on it. R5 has seen little adoption to date, with many vendors waiting for a future R6.
{
"resourceType": "Patient",
"id": "example",
"identifier": [
{"system": "urn:mrn", "value": "12345"}
],
"name": [
{"family": "SMITH", "given": ["JOHN"]}
],
"birthDate": "1980-01-15",
"gender": "male"
}In Python, a FHIR server is a connection - client = self.fhir['FHIR.Sample'] - and resources are searched, read and saved through it, as the FHIR documentation covers.
MLLP - the Minimal Lower Layer Protocol - is the transport HL7 v2 messages travel over. It is a thin framing on top of TCP - a start byte (0x0B), the message, an end pair (0x1C 0x0D) - so receivers know where one message ends and the next begins on a long-lived connection.
MLLP is not a message format - it delivers ER7 text - and it has no security of its own, which is why production deployments wrap it in TLS. Every message is answered with an acknowledgment, an ACK, and senders retransmit when none arrives.
In Zato, inbound MLLP is a channel - framing, parsing and ACKs handled for you - and outbound MLLP is self.mllp['connection-name'].send(data).
The three answer different questions. HL7 v2 and FHIR are data standards - two generations of an answer to "how is clinical information represented?". MLLP is a transport - an answer to "how do the bytes move?" - and it pairs with HL7 v2 the way HTTP pairs with FHIR.
| Term | Kind | Pairs with | One-line definition |
|---|---|---|---|
| HL7 v2 | Data standard | MLLP | Pipe-delimited clinical event messages, 1987 onward |
| FHIR | Data standard | HTTP and REST | JSON resources exchanged over web APIs |
| MLLP | Transport | HL7 v2 | TCP framing that v2 messages travel over |
| ER7 | Encoding | HL7 v2 | The pipe-and-caret text encoding of v2 messages |
| Segment | v2 structure | HL7 v2 | One line of a v2 message - MSH, PID, OBX |
| Resource | FHIR structure | FHIR | One JSON document - Patient, Observation |
| ACK | v2 message | MLLP | The acknowledgment every v2 message is answered with |
| CDA | Document standard | HL7 v3 | XML clinical documents, predecessor generation to FHIR |
"HL7 vs FHIR" is therefore not a comparison between two competing products - FHIR is an HL7 standard too - and most production systems run both - v2 feeds inside the hospital, FHIR at the edges - which is what the v2 to FHIR mapping reference and the FHIR facade pattern are for.
At the edges, yes - new regulatory programs and patient-facing APIs are FHIR. Inside hospitals, v2 feeds remain in production and the systems emitting them are expected to stay in service for years, so integration layers support both for the foreseeable future.
It saw limited adoption outside national programs built during its era - Finland's Kanta being the largest example - and HL7 moved on to FHIR. Its document format, CDA, remains widespread and is being superseded by FHIR documents.
No - plain MLLP is cleartext TCP. Production traffic between organizations runs MLLP over TLS, or inside VPNs when both ends are within one network boundary.
No port is reserved for it - 2575 is a common convention and every deployment chooses its own per channel.
Get started with Zato and connect HL7 v2 and FHIR systems in minutes.