Tool note
HL7 v2 or FHIR: Which One You Will Actually Use
Both, usually. v2 announces the events you cannot afford to miss, FHIR answers the questions your app asks, and picking one is rarely on offer.
The question usually arrives as a migration question: when do you move off HL7 v2 and onto FHIR? That framing is the problem. It is a routing question, not a migration, and for almost every real system the answer is both.
v2 announces that something happened. FHIR answers a question you asked. Those are different jobs, and a plan that collapses them into one has a hole in it.
Why this exists
The first failure mode is a budget built on the sentence “the interfaces get replaced by the API”. Then week four arrives and you find that the feed you were going to retire is how your system learns a patient was admitted without polling for it, and that a request-response API is the wrong shape for that job.
The second is assuming the write surface looks like the read surface. It does not. Epic publishes support per resource and per operation and per version: from its own index, Condition (Problems) has Read, Search and Create on R4, only Create on STU3, and only Read and Search on DSTU2. So “the write goes back over FHIR” is a claim about one resource, one operation and one version, not a general capability. Meanwhile the v2 message that carries results and documents into a chart has been in production for decades.
Here is the claim: most teams who plan a clean migration end up running both anyway, and the cost they did not budget is not the second protocol. It is owning two paths that can disagree about the same field with no written rule for who wins.
How to use it
Route per flow, never per project. For each flow answer six questions — who starts it, event or question, can it be missed, does order matter, is a human waiting, does it change the chart — then place it:
- An event that must not be lost, where order matters: a v2 feed. You get acknowledgements, store-and-forward, and the ability to resend from the queue. A poll loop is not an equivalent.
- A user in the chart who wants their own patient’s data right now: FHIR with a user-context launch. Their identity, their permissions, no new feed to build.
- A scheduled pull of a defined set: FHIR as a backend service, but only if every operation in that set exists at one version you can use. If one does not, a feed into your own store is cheaper than carrying two versions.
- A write into the chart: check the exact resource, operation and version. Where the write is not available at a version you can use, the v2 message that already exists is not a downgrade.
Then, because you kept both, write down one authoritative source per field and one rule for disagreement — before go-live, not during the first argument about it.
Where it goes wrong
This is not permission to default to v2. New reads are usually easier on FHIR: no engine build, no analyst queue, no message specification to negotiate. Defaulting to what you already know is how an organization acquires interfaces only one person can maintain.
Do not carry version answers from this page into a plan. Anything specific should be looked up in the published index the week you estimate, per resource and per operation, because that mapping moves.
Subscription and notification mechanisms exist in the FHIR specification. Whether a given site has them turned on, at which version, for which resources, is a question for that site. The spec tells you what is possible, not what is configured.
And if your organization has no interface engine and nobody who can read an MSH segment, the v2 option carries a staffing cost the protocol comparison hides completely. Choose the path you can support on the night it breaks.
Copy and Clear become available when the worksheet is ready.
INTERFACE ROUTING WORKSHEET - HL7 v2 OR FHIR, PER FLOW
Project: Site: Date:
ONE ROW PER FLOW. There is no single answer for a project.
FLOW: short name, e.g. "new admission creates the intake task"
- Who starts it? ( ) the chart ( ) my system ( ) a user in my UI
- Event or question? ( ) something happened ( ) I need to know something
- Can it be missed? ( ) never ( ) yes, it can be re-read later
- Does order matter? ( ) yes ( ) no
- Is a human waiting? ( ) seconds ( ) minutes ( ) overnight is fine
- Does it change the chart? ( ) read only ( ) writes
- Volume: exists today <> changes per day <> peak per minute <>
- Field list: name every field; "demographics" is not a field list
ROUTE IT
Event, must not be lost, order matters, no human waiting
-> HL7 v2 feed. Acknowledgements, store-and-forward, resend from the queue.
A user is in the chart and wants their own patient's data now
-> FHIR, user-context launch. Their identity, their permissions, no new feed.
Scheduled pull of a defined set, nobody waiting
-> FHIR backend service IF every operation in the set exists at one version
you can use. If one does not, feed it into your own store instead.
Write into the chart
-> Check resource AND operation AND version before you promise it. If the
write is not there at a usable version, the existing v2 message is not a
downgrade.
Two of my services need the same data
-> One ingress, one store, two readers. Never two feeds for one fact.
QUESTIONS THAT ACTUALLY DECIDE IT (ask the site; do not infer from the spec)
IF YOU KEEP BOTH (you probably will)
STAFFING - THE COST THE PROTOCOL COMPARISON HIDES
v2 needs: somebody who can read MSH / PID / OBX, an engine build, and an
analyst on their side with capacity in your window.
FHIR needs: OAuth, token handling, key rotation, and a version matrix per
operation that somebody keeps current.
Pick the path you can staff on the night it breaks, not the one that reads
better in a deck.
DECISION
Flow: Route: Why in one sentence: <>
Reviewed by: <> Date: <>