FHIR

Designing a FHIR-Native Data Platform Across EHRs

Shahnawaz Irfan
Shahnawaz Irfan
Interoperability Engineering, AST
Aug 16, 202610 min read
Two engineers review FHIR mappings beside a cluttered monitor wall in a working integration room.
TL;DR A FHIR-native platform is not a FHIR API with a fresh coat of paint. If you are supporting Epic, Oracle Health, athenahealth, PointClickCare, and a few homegrown systems at once, the platform has to normalize identity, provenance, terminology, versioning, and write-back rules before it ever becomes useful. I build this as an integration product, not a schema exercise: canonical core, vendor adapters at the edge, deterministic transforms, and backpressure-aware ingestion. If you skip that discipline, you build a shiny data swamp.

Here is the mistake I see over and over: teams hear FHIR-native and assume the answer is to expose every source system through a neat bundle of FHIR endpoints. That fails fast in production. The ugly part is not the resource model. The ugly part is that every EHR makes different promises about what a patient, encounter, medication, problem, or document actually means.

I have seen this from the inside while working on integration layers that had to survive real operational traffic, not sandbox demos. The first time we tried to treat one vendor’s Observation feed as interchangeable with another vendor’s Observation feed, we spent days untangling whether the issue was code system drift, stale patient matching, or a source application that only emitted updates after a chart closed. The lesson was simple: FHIR is the contract, but production still behaves like healthcare.

How AST Handles This: We design the platform around a canonical FHIR R4 core, then build source-specific adapters that translate vendor truth into platform truth. That keeps Epic, Oracle Health, athenahealth, and PointClickCare differences contained at the edge, where they belong. We do the same thing in our EHR integration work: one operational model, many brittle sources.

The right design starts with a strong opinion: do not make source systems your domain model. Your domain model is the care operation you are trying to support. Source systems are evidence providers. That distinction sounds academic until you try to reconcile a lab result that arrived as a FHIR DiagnosticReport in one system, an HL7v2 ORU message in another, and a PDF attachment in a third. The platform needs to absorb all three without pretending they are equivalent.


What a FHIR-native platform actually needs to do

At minimum, it has to solve four problems well.

  • Identity resolution Match a person, a practitioner, an organization, and an encounter across systems without trusting local IDs as universal truth.
  • Resource normalization Convert each source’s quirks into stable canonical resources with explicit provenance.
  • Terminology control Keep codes, value sets, and mappings deterministic so a source can drift without silently corrupting the model.
  • Lifecycle management Handle create, update, correction, and deletion semantics differently for each source and resource type.

Those are not abstract concerns. They are the usual failure modes. A patient merge in one EHR can become a duplicate in your warehouse if identity logic is weak. A terminology remap can retroactively change downstream cohort logic if you do not version codings. A source system that retracts or amends data can break auditability if you flatten history into the latest state too early.

Pro Tip: Treat provenance as first-class data, not metadata you tack on later. Every canonical resource should carry source system, source identifier, event time, ingest time, transform version, and a trace to the exact adapter rule that produced it. When a clinician questions a downstream dashboard, that trace is how you debug in minutes instead of days.

This is also where I push back on the popular platform pattern of “just land everything in a lake and model it later.” That approach looks flexible until the first operational question hits: why did yesterday’s medication count change after a vendor reconciliation? If the answer lives in a pile of raw JSON, your platform is not helping care teams. It is making them distrust data they should be able to rely on.

If you want the platform to survive the multi-EHR reality, separate ingestion from interpretation.

  1. Ingest raw events without creative rewriting Preserve the source payload, headers, timestamps, and transport context exactly as received.
  2. Classify the event Decide whether it is a patient update, clinical event, document, order, billing artifact, or administrative change.
  3. Normalize into canonical FHIR Map to your internal FHIR R4 core using deterministic rules, not ad hoc code in every downstream consumer.
  4. Validate against business rules Reject or quarantine records that violate your identity, terminology, or lifecycle rules.
  5. Publish curated views Expose downstream services to trusted datasets, not unvetted source churn.

That sequence matters because each stage has a different failure shape. Ingestion failures are usually transport or auth. Classification failures are usually source drift. Normalization failures are usually model mismatch. Business rule failures are usually policy mistakes. If you blend those layers together, every incident looks the same on the dashboard.

Warning: Do not assume FHIR bulk export solves multi-EHR harmonization. Bulk export is a delivery mechanism, not a semantic model. If the underlying sources disagree about clinical meaning, bulk export just moves the disagreement faster.

Vendor adapters, not vendor branches

I have a strong opinion here because we learned it the hard way: never fork your platform logic by EHR. The minute your Epic logic, Oracle Health logic, and athenahealth logic live in separate code paths, every new rule becomes a maintenance tax. You stop shipping a platform and start babysitting exceptions.

The cleaner pattern is an adapter layer that does three things and nothing else:

  • It translates vendor-specific transport and payload shapes into platform events.
  • It preserves source fidelity where needed.
  • It applies only source-specific mapping rules that cannot be generalized.

Everything after that should run on the same canonical pipeline. That is how you keep the platform legible. It also makes testing sane. When we modernize one of these stacks at AST, I want a failing fixture to tell me whether the issue is in the adapter, the canonical model, or the downstream consumer. If every source has its own logic tree, you lose that clarity immediately.

Design choiceWhat it looks like in productionWhy it fails or works
Vendor-specific branchesUnique Epic, Oracle Health, athenahealth code pathsFast at first, then impossible to test consistently
Canonical core with adaptersOne FHIR R4 model, source-specific edge translationEasier to govern, version, and validate
Raw lake firstEverything lands as-is, modeling deferredFlexible until operational users need trusted answers
Curated operational layerValidated FHIR resources exposed to consumersMore work up front, far less chaos later

That table is the whole argument in miniature. If your buyers only hear one thing from me, it is this: a FHIR-native platform is about control, not entitlement. You are not simply liberating data. You are defining how it becomes trustworthy across system boundaries.


The operational questions you should ask before you build

Before anyone writes code, I want these questions answered in plain English.

  • Which source system is authoritative for each data domain?
  • What happens when two systems disagree on the same clinical fact?
  • How do you represent amendments, retractions, and late-arriving data?
  • Which FHIR versions are you committing to at the core and at the edge?
  • What is the rollback plan when a source deploy breaks a mapping?

Those questions expose maturity fast. Most teams can answer the first one. The second and third are where projects get real. If you do not define conflict resolution, you will end up with whichever system happened to send data last. That is not governance. That is roulette.

We have had to solve this in production-like environments where the source behavior was not neatly documented and the edge cases only showed up after real traffic started flowing. One example that sticks with me: we assumed a patient demographic update would come through as a standard change event. It did not. The source emitted a partial record, and the downstream match logic treated the missing fields as intentional blanks. The result was a bad merge candidate. Fixing that meant teaching the adapter to distinguish absent data from cleared data. Small distinction, huge downstream impact. That is the kind of friction that makes or breaks a platform.

Pro Tip: Version your mapping rules the same way you version code. If a source mapping changes, the platform should know which records were produced under which rule set. That gives you explainability, rollback, and safer reprocessing.

One more thing I will not compromise on: keep write-back separate from read normalization. Many platforms can ingest and serve data. Fewer can safely push curated data back into an EHR or related system. Write-back is where lifecycle semantics, permissions, and transaction timing become dangerous. If you blur read and write paths, a harmless normalization change can become a clinical data error.

That is why the write-back contract has to be explicit:

  1. Define the writable objects Decide whether you are writing notes, meds, problems, tasks, orders, or administrative data.
  2. Restrict the allowed transitions Only permit updates that the target system can honor safely.
  3. Confirm acknowledgement semantics Know whether a success response means accepted, committed, or merely queued.
  4. Keep an immutable audit trail Record who or what triggered the write, when it happened, and what was sent.

That discipline is what keeps a data platform from becoming a reckless integration layer.


Where AST’s delivery experience changes the design

At AST, the pattern that keeps holding up is simple: small, dedicated pods own the integration end to end. That matters because a multi-EHR platform is not just an engineering artifact. It is a long-running operational system. Someone has to own interface drift, terminology updates, backfills, and the inevitable vendor-specific surprise that appears after go-live. We have seen this in our EHR integration work and in clinical data platforms that sit on top of live care operations.

We also learned not to over-design the first version. The temptation is to build the perfect universal model. That is how teams end up with a schema that can describe everything and help with nothing. The better move is to start with the few resource families your organization actually needs, make them rock solid, and expand only after you have proven lineage, test coverage, and operational support.

If you are planning this build, I would sequence it like this.

  1. Pick the first use case Start with one operational question the business must answer reliably, not a generic data platform charter.
  2. Inventory the source contracts Document every EHR, interface type, capacity limit, and known vendor quirk.
  3. Design the canonical minimal core Include only the resource types and extensions you truly need at launch.
  4. Build adapter tests before production feeds Use fixtures for the known edge cases: merges, amendments, duplicates, partial updates, and stale references.
  5. Define governance and rollback Make source replay, rule versioning, and quarantine workflows part of day one.
  6. Expose only trusted views Let analysts and downstream apps consume curated FHIR resources, not raw ingestion chaos.

If you want a practical mental model, think of the platform as three concentric rings: source adapters on the outside, canonical FHIR in the middle, and trusted operational services on the inside. The inner ring should never know whether its data came from Epic, Oracle Health, athenahealth, or PointClickCare. If it does, you have leaked vendor complexity into the heart of the system.

That is the whole game. Make the platform boring for consumers and ruthless about variation at the edge.

Should a multi-EHR platform store data in FHIR R4 or a custom canonical model?
Use FHIR R4 as the canonical core if your downstream ecosystem needs interoperability, but keep your internal extensions tight. I only leave the core when the business problem cannot be expressed cleanly in standard resources.
How do you handle identity matching across Epic, Oracle Health, and athenahealth?
Do not trust source IDs alone. Build an identity service that uses deterministic rules, merge history, and source provenance, then quarantine ambiguous matches instead of auto-linking them.
Can HL7v2 and FHIR live in the same platform?
Yes, and they usually have to. I treat HL7v2 as an intake rail and FHIR as the canonical model, with adapters translating transport and payload shape into the same internal pipeline.
How do you keep terminology stable when each EHR codes differently?
Version your mappings, preserve source coding, and attach the exact value set or rule set used at transform time. Otherwise, a code change can silently rewrite history.
What is the biggest mistake teams make with a FHIR-native data platform?
They confuse data ingestion with trustworthy data modeling. The platform does not become FHIR-native because it accepts FHIR payloads. It becomes FHIR-native when the canonical model, provenance, and governance are built around FHIR semantics.

Build the FHIR core before the vendor chaos spreads

If you are trying to support multiple EHRs without turning your stack into a mapping graveyard, I can help you design the canonical model, adapter layer, and operational controls that hold up in production. We build these systems to survive real interfaces, real edge cases, and real governance pressure.

Talk to our FHIR architecture team

Shahnawaz Irfan
Shahnawaz Irfan
Interoperability Engineering, AST
Shahnawaz builds the integration layer between clinical systems — FHIR R4, HL7v2 and vendor APIs — where the spec is the easy part and the edge cases in production feeds are the real work.

Comments

Comments are warming up. Live, no-sign-in discussion will appear here shortly.

Have a question now? Email info@allstartech.net.

Get in touch
Work with AST

Embed a vetted engineering pod into your team and ship clinical software faster — without cutting a compliance corner.

Book a consultation
Careers at AST

We hire engineers who want to work inside real healthcare problems — EMR, FHIR, clinical AI and the compliance that holds it together.

See open roles