Health data formats
Exchange standards, common data models, and terminologies used across clinical care and research.
Sources last verified
Health data has no single format because it has no single job. A message that moves a lab result between two hospital systems, a table that supports a retrospective cohort study, and a code that says which lab test was run are three different problems, and each has its own standard.
The most common mistake is to treat these as competitors. They are layers. A FHIR
Observation carries a LOINC code. An OMOP measurement row stores that same LOINC code, mapped
to a SNOMED concept. A C-CDA document embeds both. Asking "FHIR or OMOP?" is like asking "HTTP or
PostgreSQL?" — the answer is usually both, at different points in the pipeline.
The four layers
| Layer | Question it answers | Standards |
|---|---|---|
| Exchange | How does data move between systems? | HL7 v2, C-CDA, FHIR |
| Data model | How is data stored for analysis? | OMOP CDM, PCORnet CDM, i2b2, CDISC |
| Terminology | What does this code mean? | ICD, SNOMED CT, LOINC, RxNorm |
| Policy | What must be shared, and with whom? | USCDI, TEFCA, Information Blocking Rule |
A typical research pipeline crosses all four: data arrives over HL7 v2 or FHIR, is normalized into OMOP, is queried using SNOMED concept sets, and is governed by USCDI rules about what the source system was obliged to expose in the first place.
Which do I actually need?
| If you are... | Start with |
|---|---|
| Building an app that reads from an EHR | FHIR (R4), SMART on FHIR |
| Pulling a whole population out of an EHR | Bulk FHIR ($export), or a direct database extract |
| Running a retrospective cohort study | OMOP CDM + the OHDSI R stack |
| Running a multi-site network study | OMOP or PCORnet, whichever your network already speaks |
| Submitting a trial to the FDA or EMA | CDISC SDTM and ADaM — non-negotiable |
| Integrating with a hospital interface engine | HL7 v2, and expect to meet Mirth Connect |
| Doing NLP on clinical notes | UMLS, plus SNOMED CT and RxNorm for normalization |
| Reconciling codes between two datasets | UMLS, or the OHDSI vocabulary tables via Athena |
How to read the tooling chips
Every format below carries a row of chips reporting how well each language handles it. The color is maturity, not existence — the gap between a real library and a weekend project is the single most useful thing to know before you commit to a stack.
Chips are followed by a table with the actual package name and the caveat that matters. Package availability was verified against PyPI, CRAN, npm, crates.io, and the Julia General registry in September 2026; spec versions were checked against the publishing bodies at the same time.
PythonRJuliaRustTaken across the whole domain, the ranking is stable and worth stating up front: Python and R are the only two languages where every layer is covered. Java is the reference implementation language for the exchange standards — HAPI is what the specs are tested against — so serious HL7 v2 and FHIR work reaches for a JVM eventually. Julia and Rust have real entries in a few places and nothing at all in most. TypeScript is strong for FHIR specifically and thin everywhere else.
A note on synthetic data
Do not develop against real patient data. Synthea generates synthetic patient populations with complete longitudinal histories and exports directly to FHIR, C-CDA, and CSV; ETL-Synthea loads the result into OMOP. Every example on these pages is synthetic and hand-written for illustration.
For OMOP specifically, the Eunomia R package ships a small pre-built CDM in a local DuckDB or
SQLite file, which is the fastest way to have a queryable CDM without an ETL.
Scope
These pages cover the exchange, data model, and terminology layers. Two adjacent areas are deliberately out of scope: claims and administrative formats (X12 837/835/834, NCPDP, UB-04) and imaging and signals (DICOM, NIfTI, BIDS, EDF). Both are large enough to deserve their own treatment.