If you work with clinical data for long enough, you will hear someone ask whether the organisation should "go FHIR or go OMOP". It is the wrong question. HL7 FHIR and the OMOP Common Data Model solve different problems, and most serious healthcare data platforms need both.
I have worked hands-on with OMOP and the OHDSI tool stack (ATLAS, WebAPI and Broadsea), and that work fed into peer-reviewed research published in Science Immunology. This is the architecture I would sketch on a whiteboard for a hospital group, a research organisation or a health-tech company starting today.
What each standard is for
| HL7 FHIR | OMOP CDM | |
|---|---|---|
| Primary purpose | Exchanging data between systems | Analysing data across sources |
| Shape | Resources (Patient, Observation, MedicationRequest...) over REST APIs | Relational tables (person, condition_occurrence, drug_exposure, measurement...) |
| Codes | Carries source codes as received | Maps everything to standard concepts |
| Best at | Real-time integration, apps, patient access | Cohorts, population analytics, reproducible studies |
| Ecosystem | EHR vendors, app developers, regulators | OHDSI community: ATLAS, HADES, network studies |
The short version: FHIR is the shipping container, OMOP is the warehouse with everything sorted onto standard shelves.
The reference pipeline
Sources Intake Terminology Analytics Use
------- ------ ----------- --------- ---
EHR (HL7 v2) --> --> ATLAS cohorts
Labs --> FHIR --> map to SNOMED --> OMOP CDM ---- --> Research studies
Claims --> server / LOINC, RxNorm (+ era --> Dashboards
Devices --> bulk export concept mapping tables) --> Clinical AI
de-identification, consent, access control and audit at every hop
Each stage has one job. Keeping them separate is what makes the platform maintainable.
Stage 1: intake through FHIR
Normalise everything you can into FHIR resources at the edge. Modern EHRs expose FHIR APIs and bulk export; for legacy HL7 v2 feeds, flat files and claims, write adapters that produce FHIR. The benefits are practical:
- One intake format means one set of validation rules, not one per source.
- Provenance is easier to keep: each resource can record where it came from and when.
- The same intake layer serves operational use cases, such as apps and patient access, not just analytics.
Do not try to fix every code at this stage. Keep the source codes faithfully. Mapping comes next.
Stage 2: terminology mapping
This is where most of the intellectual work lives. Source systems use local codes, ICD-10, CPT, proprietary lab codes and free text. OMOP requires mapping these to standard concepts, chiefly:
- SNOMED CT for conditions, procedures and observations
- LOINC for laboratory tests and measurements
- RxNorm for drugs
The OHDSI standardised vocabularies provide most of the mappings for common code systems. The hard part is local codes. Build a terminology service that holds your mappings, records who approved each one, and versions them. Track mapping coverage as a metric: the percentage of records, and of distinct codes, that map to a standard concept. Unmapped high-volume codes are your backlog.
The vocabularies are, in effect, a shared ontology for medicine. That is why OMOP works across institutions: everyone agrees what the concepts mean. I discuss the general idea in Ontology vs knowledge graph vs semantic layer.
Stage 3: load into OMOP CDM
With codes mapped, transform FHIR resources into OMOP tables. A rough correspondence:
- Patient to
person, with location and demographics - Encounter to
visit_occurrence - Condition to
condition_occurrence - MedicationRequest and MedicationAdministration to
drug_exposure - Observation (labs and vitals) to
measurementorobservation, depending on the concept domain - Procedure to
procedure_occurrence
Note that the target table is decided by the domain of the mapped concept, not by the FHIR resource type. This catches many teams out. Then build the derived era tables (condition and drug eras), which make cohort logic far simpler.
Keep the ETL in code, under version control, with tests. Every change to mapping logic changes research results, so you need to know exactly which version produced which dataset.
Stage 4: cohorts and research with OHDSI
Once data is in OMOP, the OHDSI tools become available. ATLAS lets analysts define cohorts ("adults with type 2 diabetes started on drug X with an HbA1c above Y") visually, and those definitions are portable. The same cohort definition can run at another OMOP site without rewriting. Broadsea packages the stack in containers, which makes it much easier to stand up consistent environments.
This portability is the real prize. Studies become reproducible, and network research across institutions becomes possible without moving patient data.
De-identification and HIPAA
The data model does nothing for privacy on its own. Privacy has to be designed in at every hop:
- Separate identified and research zones. Identified data stays in the intake zone; the research OMOP instance holds de-identified or limited datasets.
- De-identification pipeline. Remove or transform direct identifiers, shift dates consistently per person, generalise rare values, and document the method (Safe Harbor or expert determination under HIPAA).
- Consent and purpose. Record what each dataset may be used for, and enforce it in access control.
- Least privilege and audit. Role-based access, encryption at rest and in transit, and immutable audit logs of who queried what.
- Residency. Know where each dataset physically lives; this matters for US and Gulf deployments alike.
Data quality and common pitfalls
Run data quality checks on every load. The OHDSI Data Quality Dashboard is a good start, alongside your own checks on volumes, mapping coverage and plausibility (birth dates in the future, lab values in impossible ranges). Pitfalls I see repeatedly:
- Mapping by hand in spreadsheets with no versioning or approval trail.
- Losing source values. Always keep the original code and value alongside the standard concept.
- Treating OMOP as the operational store. It is an analytical model; serve apps from FHIR.
- Underestimating units. Lab results in mixed units silently ruin measurement analyses.
- Adding AI before the data is governed. Clinical AI is only as trustworthy as the provenance and quality underneath it.
Where FHIR and OMOP disagree, and how to handle it
The two standards were designed by different communities for different jobs, so the mapping is never perfectly clean. A few places where I spend time on every project:
Time
FHIR records rich timing: effective periods, issued times, recorded dates, and status changes over time. OMOP wants a start date, an end date and sometimes a datetime. You have to decide, and document, which FHIR timestamp becomes the OMOP event date. For a lab result, is it when the sample was taken or when the result was issued? For research the collection time is usually right, but write the rule down, because analysts will ask.
Status and corrections
FHIR resources change. A medication request can be cancelled, an observation can be amended, a condition can be marked as entered in error. OMOP is closer to a record of what happened. Your ETL needs a clear policy for each status: load it, exclude it, or replace the earlier record. Getting this wrong quietly inflates counts.
Free text
Much of the clinically useful detail lives in notes, not codes. OMOP has a note table and an NLP table for extracted concepts. If you plan to extract concepts from text, whether with classic NLP or an LLM, keep the extraction method and version with every derived record, so researchers can filter by how confident they should be.
Episodes and context
FHIR links many resources to an Encounter. OMOP links events to visits, but the visit model is simpler. Decide early how you will represent things like an emergency visit that becomes an inpatient stay, because it affects every length-of-stay analysis later.
Sizing the team and the timeline
People often ask how long this takes. It depends far more on the sources than on the technology. One modern EHR with good FHIR support and a clean lab feed is a very different project from a dozen legacy systems with local codes. What I can say with confidence is how the effort usually splits:
- Intake and adapters are predictable engineering work, once you have access to the sources.
- Terminology mapping is the long tail. The common codes map quickly; the local codes take clinical input and patience.
- Data quality and validation never finish. Budget for them as an ongoing activity, not a phase.
- Governance, meaning agreements on access, consent and use, often takes longer than the build. Start those conversations on day one.
The team that does this well pairs data engineers with someone who understands clinical coding. Neither group can do it alone. A good first milestone is one source, fully mapped and validated in OMOP, with a single real cohort defined in ATLAS and checked by a clinician. That proves the pipeline end to end and gives everyone something concrete to critique.
Layering AI on top
Once data is standardised and governed, AI becomes much safer to add. Standard concepts give models a consistent vocabulary; provenance lets you trace any answer back to source records; access controls already exist. I would still keep clinical AI behind human review, ground it in the governed data rather than raw notes alone, and evaluate it against cases reviewed by clinicians. For sensitive workloads, running models on your own hardware keeps patient data inside your environment.
How I can help
I design healthcare data platforms that take fragmented clinical feeds through FHIR and standard vocabularies into OMOP, with privacy built in, and then layer clinical AI on top of governed data.
For a quick read on your situation, try the challenge analyser and choose "Healthcare interoperability", or see the healthcare case study in my work.