If you have ever built an EHR feature and thought "the patient model is basically done, how hard can the rest be," this post is for you. The chart, the structured record of problems, meds, allergies, results, is genuinely the easy part. You could model a workable version in a weekend. The part that decides whether your system survives contact with a real hospital is the integration layer, and it is where most custom EHR projects quietly die.
Healthcare data does not live in your database. It lives everywhere, in incompatible formats, behind systems that were never designed to cooperate. So interoperability is not a feature you add; it is the defining engineering constraint of the whole project. Let's get concrete about the two standards you will fight with and how to structure the workstream around them.
HL7 v2: the ugly protocol that runs everything
HL7 v2 is the decades-old messaging format that still moves the majority of clinical data between hospital systems. It is pipe-delimited, segment-based, and everywhere. A typical message looks like an ADT (admit/discharge/transfer) or ORU (observation result) event, segments such as MSH, PID, OBR, and OBX separated by | and ^.
It is unglamorous, and it is not going away. The trap is assuming "standard" means "consistent." It does not. Every hospital implements HL7 v2 with local quirks: optional segments that are mandatory in practice, custom Z-segments, subtly different field usage. Your parser has to be tolerant of variation the spec technically permits but nobody warned you about.
MSH|^~\&|LAB|HOSP|EHR|CLINIC|202607161230||ORU^R01|MSG00001|P|2.5.1
PID|1||MRN12345^^^HOSP^MR||DOE^JANE||19850214|F
OBR|1||ACC987|CBC^Complete Blood Count^L
OBX|1|NM|WBC^White Blood Cell^L||11.2|10*3/uL|4.0-10.0|H|||F
Notice the H flag on that last segment, an abnormal (high) result. Miss the logic that surfaces and tracks acknowledgment of that flag and you have a patient-safety defect, not a cosmetic bug.
FHIR: the modern standard you build new work against
FHIR (Fast Healthcare Interoperability Resources) is the RESTful, JSON-based standard regulators are actively pushing the industry toward. For anything new, build against FHIR. Instead of parsing delimited segments you work with resources over HTTP:
GET /Patient/12345
GET /Observation?patient=12345&category=laboratory&code=http://loinc.org|6690-2
POST /MedicationRequest
Resources like Patient, Observation, Condition, MedicationRequest, and AllergyIntolerance map cleanly to your domain, and the payloads are readable JSON. But "RESTful and modern" still is not plug-and-play. FHIR servers vary in which resources and which version (DSTU2 vs STU3 vs R4 vs R5) they support, in which search parameters they implement, and in how strictly they validate. You will write server-specific adapters no matter how clean the spec looks.
The integration engine: isolate the mess
The architectural move that makes this manageable is to never let external protocol details leak into your core. Stand up a dedicated integration engine, an anti-corruption layer, that speaks HL7 v2 and FHIR outward and exposes clean, normalized domain events inward.
Responsibilities of that layer:
- Inbound parsing and validation of HL7 v2 messages and FHIR resources, tolerant of per-source quirks.
- Normalization into your internal canonical model so the rest of the system never sees a pipe delimiter or a vendor's FHIR extension.
- Outbound mapping back to HL7/FHIR for each partner's specific dialect.
- A test harness that replays real, de-identified message samples, because synthetic happy-path fixtures hide exactly the bugs that bite in production.
- Observability and retries, since feeds drop, reorder, and duplicate.
Treat this as its own workstream with its own maintenance budget. Teams that budget for it succeed; teams that treat it as a two-week connector task ship something that works in the demo and fails in the field.
Terminology mapping: the silent data-corruption source
Here is the subtlety that gets skipped and surfaces months later as subtly wrong data. Even when messages parse perfectly, the codes inside them come from different vocabularies:
- SNOMED CT for clinical findings and problems.
- LOINC for lab tests and observations.
- RxNorm for medications.
- ICD-10 for diagnoses and billing.
A lab result coded in one source's local dictionary has to be reconciled to LOINC; a medication string has to resolve to RxNorm. If you skip terminology mapping, your data is not obviously broken, it is quietly wrong, and quietly wrong in a medication or allergy list is the worst failure mode in the building. Stand up a terminology service, back it with the standard code systems, and version your mappings so you can trace how a value was interpreted.
A minimal reference architecture
Putting it together, a durable EHR separates concerns into layers that can evolve independently:
- Clinical data repository — source of truth, modeled around interoperable resources rather than a bespoke schema you will regret.
- Integration layer — the engine above, speaking HL7 and FHIR to labs, pharmacies, imaging, and payers.
- Terminology service — SNOMED/LOINC/RxNorm/ICD-10 mapping, versioned.
- Workflow and rules layer — clinical logic, decision support, orchestration.
- AI services layer — documentation, summarization, coding, grounded in the repository and always auditable.
- Role-specific interfaces over shared APIs, separate front ends for clinicians, staff, and patients rather than one screen bent to serve everyone badly.
Keeping these decoupled is what lets you swap an AI model, add a specialty workflow, or connect a new hospital without destabilizing the system. If you are extending this into a multi-tenant product, it typically grows into a broader SaaS platform with per-organization configuration.
Practical takeaways
- Support both: FHIR for new, RESTful exchange; HL7 v2 for the large installed base of legacy feeds.
- Build an anti-corruption integration layer so protocol details never leak into core code.
- Test against real de-identified messages, never synthetic happy-path fixtures.
- Treat terminology mapping as first-class; silent miscoding is worse than a crash.
- Budget interoperability as a permanent workstream, not a one-time task.
For the full picture, architecture, compliance, cost, and where AI actually helps, TechCirkle's complete guide to EHR software development goes deeper than a single post can. If you are scoping an integration-heavy build and want engineering input, it is worth reaching out to a team that has shipped these layers before.
Frequently Asked Questions
What is the difference between HL7 v2 and FHIR?
HL7 v2 is a decades-old, pipe-delimited messaging format that still moves most clinical data between hospital systems, while FHIR is a modern, RESTful, JSON-based standard built around resources accessed over HTTP. HL7 v2 is ubiquitous in legacy feeds; FHIR is what regulators push toward and what you should build new interfaces against. A realistic EHR supports both rather than choosing one.
Do I need an integration engine to build an EHR?
Practically, yes. An integration engine acts as an anti-corruption layer that parses and normalizes inbound HL7 and FHIR data, maps outbound messages to each partner's dialect, and keeps protocol details from leaking into your core domain. Without it, per-source quirks and vendor-specific extensions contaminate your business logic, making the system brittle and nearly impossible to extend to new hospitals or labs.
Why does terminology mapping matter in EHR interoperability?
Because messages that parse perfectly can still carry codes from different vocabularies, SNOMED CT, LOINC, RxNorm, ICD-10, that must be reconciled to a canonical system. Skip the mapping and your data is not obviously broken, it is subtly wrong, which in a medication or allergy list is a patient-safety risk. A versioned terminology service lets you reconcile codes and trace how each value was interpreted.
Which FHIR version should an EHR support?
It depends on the servers you integrate with, since real deployments span DSTU2, STU3, R4, and R5, and they differ in supported resources, search parameters, and validation strictness. R4 is the common modern baseline, but you will still write server-specific adapters. Design your integration layer to normalize across versions into one internal canonical model rather than coupling core code to any single FHIR release.
How do you test an EHR integration layer reliably?
Replay real, de-identified message samples through a dedicated test harness rather than relying on synthetic happy-path fixtures. Production feeds drop, reorder, duplicate, and include per-source quirks the spec technically permits, and only realistic samples surface those bugs before clinicians do. Pair that with observability and retry logic, because interoperability is a continuous property to maintain, not a one-time verification step.
Is FHIR mandatory for EHR development in 2026?
FHIR is not universally mandatory for every system, but it is the direction regulators are actively pushing the industry toward, and building new interfaces against it is the safe default. Many environments still depend on HL7 v2 for existing feeds, so a realistic EHR supports both: FHIR for modern RESTful exchange and HL7 v2 for the large installed base of legacy hospital systems.


Top comments (0)