<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>FHIR for Data Science Blog</title>
        <link>https://fhir4ds.com/blog/</link>
        <description>FHIR for Data Science Blog</description>
        <lastBuildDate>Wed, 04 Nov 2026 10:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[What the All of Us FHIR-vs-OMOP Study Actually Measured]]></title>
            <link>https://fhir4ds.com/blog/fhir-vs-omop-all-of-us/</link>
            <guid>https://fhir4ds.com/blog/fhir-vs-omop-all-of-us/</guid>
            <pubDate>Wed, 04 Nov 2026 10:00:00 GMT</pubDate>
            <description><![CDATA[The 2026 All of Us comparison found OMOP dramatically richer than FHIR — but it compared acquisition pipelines, not data models. What that means for FHIR analytics, with the standard-artifact answer.]]></description>
            <content:encoded><![CDATA[<p>A 2026 study from the All of Us Research Program compared
the same 29,512 participants' data as OMOP tables and as FHIR R4 payloads —
Patterson et al., <em>JAMIA</em> 33(9):1593–1604
(<a href="https://doi.org/10.1093/jamia/ocag095" target="_blank" rel="noopener noreferrer" class="">doi:10.1093/jamia/ocag095</a>). The
headline numbers are stark:</p>
<table><thead><tr><th>Median events per person</th><th>OMOP</th><th>FHIR</th></tr></thead><tbody><tr><td>Measurement</td><td>846</td><td>832</td></tr><tr><td>Condition</td><td>258</td><td>11</td></tr><tr><td>Procedure</td><td>72</td><td>4</td></tr><tr><td>Participants with visits/encounters</td><td>97%</td><td>1.5%</td></tr></tbody></table>
<p>The conclusion many people draw — <em>OMOP is richer, FHIR is not ready for
research</em> — deserves a harder look, because the study itself tells you
exactly what it measured. It is careful, honest work — and with AMIA
ahead, it is likely to shape how people talk about FHIR analytics. Here is
what it did and did not
show, and the concrete answer to the barrier it identified.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-study-actually-compared">What the study actually compared<a href="https://fhir4ds.com/blog/fhir-vs-omop-all-of-us/#what-the-study-actually-compared" class="hash-link" aria-label="Direct link to What the study actually compared" title="Direct link to What the study actually compared" translate="no">​</a></h2>
<p>The two data streams reached the researchers through very different
pipelines:</p>
<ul>
<li class=""><strong>OMOP</strong> arrived through institution-level ETL, built per site by
engineers who map concepts from <em>anywhere</em> in the EHR into the standard
vocabulary, with an iterative submission-and-feedback loop until the data
passed quality review.</li>
<li class=""><strong>FHIR</strong> arrived as participants connected to FHIR providers through
digital participant portals, which <em>"extract data via API from clinical
datasets in the FHIR format"</em>; a data aggregator then <em>"moderately
standardizes the data and submits it to AoURP"</em> — with, per the authors,
<em>"no feedback cycle,"</em> and FHIR limited to <em>"standard mappings used in its
default bulk export functionality,"</em> which are determined by the EHR
vendor.</li>
</ul>
<p>The authors say this themselves: <em>"clinical data documented in an unexpected
area of the EHR are often excluded from FHIR exports"</em> because vendor
defaults decide what leaves the building. But the underlying challenge is
not FHIR-specific. Clinical data that is never properly mapped and encoded —
documented in free text instead of coded into structured entries — is hard
to use in <em>either</em> standard; OMOP confronts exactly the same problem and
solves it by throwing institution-funded ETL engineers at the source. That
is a curation investment, not a model capability. FHIR itself is very rich
in the information it can hold and handle — when data is properly encoded
into its resources, nothing in the Condition or Procedure domains is beyond
it. The Condition 258-vs-11 gap is therefore a statement about acquisition
pipelines and encoding discipline, not about the expressive power of the
two data models.</p>
<p>The study also quantified a real and durable tradeoff: FHIR's blocking,
ingestion-time validation produced structurally cleaner data (unique ids,
resolvable references), while OMOP's non-blocking post-hoc checks traded
conformance for yield. Both findings are worth keeping.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-we-agree">Where we agree<a href="https://fhir4ds.com/blog/fhir-vs-omop-all-of-us/#where-we-agree" class="hash-link" aria-label="Direct link to Where we agree" title="Direct link to Where we agree" translate="no">​</a></h2>
<p><strong>OMOP is the right tool for observational research today.</strong> It is
purpose-built for it: flat, regular tables, standardized concept ids, and a
decade of methods and tooling that assume its shape. If your institution
has already paid for an OMOP ETL, use it. We are not arguing against OMOP —
FHIR4DS (the open-source engine behind this blog) ships an OMOP CDM
mapping library, and the
<a class="" href="https://fhir4ds.com/docs/examples/fhir-to-omop/">FHIR → OMOP walkthrough</a> exists precisely
because OMOP is often the destination downstream teams need.</p>
<p><strong>The gaps the study found are real — but they live in acquisition and
encoding, not in FHIR.</strong> Data that is never properly mapped and coded —
documented in text rather than structured entries — yields poor research
data in <em>either</em> standard; OMOP overcomes it only through funded ETL
curation, and default FHIR exports simply haven't had that curation. The
encounter gap is the clearest case: the study's window (January 2020 –
March 2024) sat entirely inside the <strong>USCDI v1</strong> regulatory baseline,
which had no Encounter data class at all — encounters only entered USCDI
in <strong>v2 (2021)</strong>, and only as a voluntary update; the mandatory
certification baseline (USCDI v3, per the HTI-1 rule) took effect
<strong>January 1, 2026</strong>. The finding that just 1.5% of participants had FHIR
Encounters (versus 97% with OMOP visits) measures a v1-era export floor,
not a FHIR limitation — and the mandate the authors said would fix it
had already taken effect by the time the paper published.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-the-framing-needs-a-correction">Where the framing needs a correction<a href="https://fhir4ds.com/blog/fhir-vs-omop-all-of-us/#where-the-framing-needs-a-correction" class="hash-link" aria-label="Direct link to Where the framing needs a correction" title="Direct link to Where the framing needs a correction" translate="no">​</a></h2>
<p>The headline many people take away — "OMOP has 20× more clinical data than
FHIR" — conflates the data model with the pipeline that filled it. The fair
statement is:</p>
<blockquote>
<p>Institutionally-funded ETL currently yields more research-ready data than
zero-configuration vendor exports, regardless of the destination model.</p>
</blockquote>
<p>Three observations from the study itself point at what is actually missing
— and each one is answered by a standard that already exists. The relevant
body of work is <strong>SQL-on-FHIR v2</strong>, an HL7-community specification —
maintained under the FHIR project, with an official conformance test
suite — that makes FHIR resources queryable as tables. Its artifacts, plus
one plain-FHIR resource for vocabulary, are worth knowing by name because
they turn "extracting data from FHIR payloads" from a per-institution
engineering project into a set of small, versioned, shareable files.
FHIR4DS is a DuckDB-based engine that runs all of them — plus CQL and
FHIRPath — directly over FHIR payloads, in a notebook or in the browser.</p>
<p><strong>1. The FHIR analyses were only possible after a third party added a
terminology-mapping layer.</strong> Raw FHIR payloads were not directly analyzable
by the research team without it. That is a correct diagnosis of the
<em>tooling</em>, not the data — and the vocabulary step is a solved problem in
the specification itself. A <strong>ConceptMap</strong> is a standard FHIR resource
whose entire job is "this code in this system means that concept" —
vocabulary translation as <em>data</em> rather than as a bespoke mapping program:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token property" style="color:hsl(355, 65%, 65%)">"resourceType"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"ConceptMap"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token property" style="color:hsl(355, 65%, 65%)">"group"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token property" style="color:hsl(355, 65%, 65%)">"source"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"http://hl7.org/fhir/administrative-gender"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token property" style="color:hsl(355, 65%, 65%)">"target"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"urn:omop:concept"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token property" style="color:hsl(355, 65%, 65%)">"element"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"code"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"male"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain">   </span><span class="token property" style="color:hsl(355, 65%, 65%)">"target"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"code"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"8507"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"equivalence"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"equivalent"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"code"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"female"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"target"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"code"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"8532"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"equivalence"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"equivalent"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></div></code></pre></div></div>
<p>Flatten it once with a ViewDefinition (next paragraph) and it is an
ordinary lookup table — <code>source_system + code → concept_id</code> — joined in a
query. No third party required: the mapping ships with the pipeline, and
the <a class="" href="https://fhir4ds.com/docs/user-guide/modeling/omop-mapping/">OMOP CDM mapping library</a>
carries one covering 108,683 codes.</p>
<p><strong>2. The stated obstacle was "extracting data from FHIR payloads"</strong> — a
data-engineering problem, not a clinical-content problem. And the gap stops
being expensive when the extraction becomes a <strong>shareable standard
artifact</strong>. The <strong>ViewDefinition</strong> is SQL-on-FHIR v2's reshaping artifact:
a small JSON file that declares, per resource type, which elements become
which columns, with FHIRPath expressions for paths — declarative and
precise rather than procedural code. Where an OMOP ETL is months of local
engineering, the same reshape is one of these, runnable by any conformant
engine against any FHIR export:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token property" style="color:hsl(355, 65%, 65%)">"name"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"omop_person_source"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token property" style="color:hsl(355, 65%, 65%)">"resource"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"Patient"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token property" style="color:hsl(355, 65%, 65%)">"select"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"column"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"name"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"person_source_value"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"path"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"id"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"type"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"id"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"name"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"year_of_birth"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"path"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"birthDate.substring(0, 4)"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"type"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"string"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"name"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"gender_source_value"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"path"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"gender"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token property" style="color:hsl(355, 65%, 65%)">"type"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"code"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></div></code></pre></div></div>
<p>A <strong>SQLQuery</strong> then composes the views: a standard FHIR <code>Library</code> resource
whose body is ordinary SQL over the view names — joins, unions, and
derived columns live there, portable across engines. Write the mapping
once, version it, publish it, cite it — a mapping you <em>review and share</em>,
not one you rebuild at every institution. The
<a class="" href="https://fhir4ds.com/docs/examples/fhir-to-omop/">FHIR → OMOP walkthrough</a> builds a complete
<code>person</code> table this way, live in the browser, and every other OMOP table is
the same recipe.</p>
<p><strong>3. FHIR captured what OMOP could not.</strong> 6,300 participants had
multi-provider FHIR data versus 20 in OMOP, and 18.4% of timeline segments
existed <em>only</em> in FHIR — care delivered at outside institutions the
institutional ETL never saw. The study recommends FHIR as a <em>supplement</em>;
we agree, and would add that a supplement you cannot query is a supplement
you cannot use. Native FHIR querying — ViewDefinitions, CQL, FHIRPath,
straight over the payloads — makes the multi-provider slice analyzable the
day it lands, with no second ETL project. The two models compose rather
than compete: query FHIR natively for what only FHIR has, and project into
OMOP where the research ecosystem demands it, from the same standard
artifacts.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="standards-conformance-not-vendor-claims">Standards conformance, not vendor claims<a href="https://fhir4ds.com/blog/fhir-vs-omop-all-of-us/#standards-conformance-not-vendor-claims" class="hash-link" aria-label="Direct link to Standards conformance, not vendor claims" title="Direct link to Standards conformance, not vendor claims" translate="no">​</a></h2>
<p>Skeptics are right to ask what "spec compliant" means. Each of the
specifications FHIR4DS implements ships an HL7-community-built reference
implementation and an official test suite designed to validate other
implementations. FHIR4DS passes all of them — <strong>2,785 official conformance
tests at 100%</strong> in release 0.0.21:</p>
<table><thead><tr><th>Suite</th><th>Tests</th><th>Passing</th></tr></thead><tbody><tr><td>CQL — official HL7 <code>cql-tests</code> corpus</td><td>1,706</td><td>100%</td></tr><tr><td>FHIRPath — official reference suite</td><td>935</td><td>100%</td></tr><tr><td>SQL-on-FHIR v2 — official <code>spec_tests</code></td><td>144</td><td>100%</td></tr><tr><td>CMS eCQM measures (QI-Core 2025) — evaluated end-to-end</td><td>47</td><td>100%</td></tr></tbody></table>
<p>The OMOP CDM v5.5 mapping library carries its own example suite (38
expected-output tests — OMOP has no official test suite), kept green in
the same runner.</p>
<p>The conformance runner ships in the repository — anyone can reproduce the
numbers.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-bottom-line">The bottom line<a href="https://fhir4ds.com/blog/fhir-vs-omop-all-of-us/#the-bottom-line" class="hash-link" aria-label="Direct link to The bottom line" title="Direct link to The bottom line" translate="no">​</a></h2>
<p>The All of Us study is a valuable census of what today's <em>default</em>
acquisition paths deliver, and its recommendation of FHIR as a supplement
to OMOP is sound for programs that already have both. But its own evidence
points past its framing: the cost it identified was not FHIR's ability to
represent clinical reality — it was the absence of native analysis tooling
for FHIR payloads. That absence is what FHIR4DS removes. As bulk exports
fatten under the USCDI v3 mandate (in force since January 2026) and
standard mapping artifacts accumulate, the "OMOP richer, FHIR raw"
tradeoff narrows from both ends — and the multi-provider data only FHIR
captures becomes queryable the day it arrives.</p>
<p>Want to see the extraction barrier dissolved end to end? Run the
<a class="" href="https://fhir4ds.com/docs/examples/fhir-to-omop/">FHIR → OMOP walkthrough</a> — it executes live
in your browser, standard artifacts only.</p>]]></content:encoded>
            <category>FHIR</category>
            <category>OMOP</category>
            <category>SQL-on-FHIR</category>
            <category>Analytics</category>
        </item>
        <item>
            <title><![CDATA[Standards-Compliant Clinical Reasoning, Zero-ETL Analytics & Query-Time OMOP Mapping]]></title>
            <link>https://fhir4ds.com/blog/fhir4ds-solution-brief/</link>
            <guid>https://fhir4ds.com/blog/fhir4ds-solution-brief/</guid>
            <pubDate>Sun, 01 Nov 2026 09:00:00 GMT</pubDate>
            <description><![CDATA[The FHIR4DS executive solution brief: open-standards compliance verified against the official HL7 test suites, zero-infrastructure analytics, and query-time OMOP CDM v5.5 mapping with the performance numbers behind it.]]></description>
            <content:encoded><![CDATA[<p>Translational researchers, clinical informaticians, and healthcare data
architects face a fundamental architectural divide: operational systems
exchange deeply nested FHIR JSON, while observational research, clinical
logic evaluation, and population analytics require relational tables.
FHIR4DS bridges this divide with an open-standards, SQL-native analytical
engine built directly on DuckDB.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="open-standards-compliance--interoperability">Open Standards Compliance &amp; Interoperability<a href="https://fhir4ds.com/blog/fhir4ds-solution-brief/#open-standards-compliance--interoperability" class="hash-link" aria-label="Direct link to Open Standards Compliance &amp; Interoperability" title="Direct link to Open Standards Compliance &amp; Interoperability" translate="no">​</a></h2>
<p>FHIR4DS is engineered for 100% specification compliance with official
healthcare standards, ensuring your clinical logic and data models remain
completely portable without proprietary lock-in:</p>
<ol>
<li class=""><strong>HL7 FHIRPath</strong> — the standard expression language for navigating
complex clinical trees. Enables path traversal, deep collection
extraction, and polymorphic choice types directly within SQL queries
over raw FHIR JSON.</li>
<li class=""><strong>HL7 Clinical Quality Language (CQL)</strong> — the interoperable standard
for expressing computable clinical knowledge. Authors write
human-readable clinical definitions — patient cohort eligibility,
screening criteria, disease phenotypes — that compile directly to
portable SQL.</li>
<li class=""><strong>HL7 SQL-on-FHIR v2</strong> — the open community standard for defining
flattened, tabular views of hierarchical FHIR resources. An
interoperable, vendor-neutral method to reshape complex JSON documents
into clean relational projections.</li>
<li class=""><strong>OHDSI OMOP Common Data Model (v5.5)</strong> — the international standard
for observational health research. FHIR4DS maps FHIR R4 to OMOP CDM
v5.5 tables on-the-fly, resolving concepts across standard medical
vocabularies at query time without offline ETL staging.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-compliance-claim-is-tested-against">What the compliance claim is tested against<a href="https://fhir4ds.com/blog/fhir4ds-solution-brief/#what-the-compliance-claim-is-tested-against" class="hash-link" aria-label="Direct link to What the compliance claim is tested against" title="Direct link to What the compliance claim is tested against" translate="no">​</a></h3>
<p>Each of the specs FHIR4DS implements — FHIRPath, CQL, and SQL-on-FHIR v2
— ships with its own HL7-community-built reference implementation and a
test suite designed to validate other implementations. FHIR4DS passes
<strong>all 2,785 of them at 100%</strong>:</p>
<table><thead><tr><th>Suite</th><th>Tests</th><th>Passing</th></tr></thead><tbody><tr><td>CQL — official HL7 <code>cql-tests</code> corpus</td><td>1,706</td><td>100%</td></tr><tr><td>FHIRPath — official reference suite</td><td>935</td><td>100%</td></tr><tr><td>SQL-on-FHIR v2 — official <code>spec_tests</code></td><td>144</td><td>100%</td></tr><tr><td>CMS eCQM measures (QI-Core 2025) — evaluated end-to-end</td><td>47</td><td>100%</td></tr></tbody></table>
<p>The OMOP CDM v5.5 mapping library carries its own example suite (38
expected-output tests — OMOP has no official test suite), kept green in
the same runner.</p>
<p>These are not self-authored checks where it matters: the FHIRPath suite
is the one the reference evaluator runs, the CQL suite is the official HL7
<code>cql-tests</code> corpus, and the ViewDefinition suite is the SQL-on-FHIR
community's <code>spec_tests</code>. Where an official suite disagrees with the
implementation, the suite wins — and the conformance runner ships in the
repository so anyone can reproduce the numbers. Beyond the suites, all 47
CMS eCQM measures from the QI-Core 2025 content package evaluate
end-to-end (real FHIRHelpers/QICoreCommon resolution, real ValueSets,
real patient data), and the OMOP CDM v5.5 mapping library carries its
own example suite (38 expected-output tests — OMOP has no official test
suite) kept green in the same runner.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ease-of-use-zero-infrastructure-run-anywhere">Ease of Use: Zero Infrastructure, Run Anywhere<a href="https://fhir4ds.com/blog/fhir4ds-solution-brief/#ease-of-use-zero-infrastructure-run-anywhere" class="hash-link" aria-label="Direct link to Ease of Use: Zero Infrastructure, Run Anywhere" title="Direct link to Ease of Use: Zero Infrastructure, Run Anywhere" translate="no">​</a></h2>
<ul>
<li class=""><strong>Runs directly in notebooks &amp; Python</strong> — no JVM, no Docker
containers, no server infrastructure. <code>pip install fhir4ds-v2</code> and
execute clinical queries inside local Jupyter notebooks, Python
scripts, or automated analytical workflows.</li>
<li class=""><strong>Zero-ETL direct data attachment</strong> — mount raw clinical data where it
already lives: local/cloud Parquet, NDJSON bulk exports, AWS S3,
PostgreSQL/HAPI read replicas, and MongoDB, with no pre-flattening,
data duplication, or pipeline synchronization lag.</li>
<li class=""><strong>Native DataFrame &amp; lakehouse ecosystem</strong> — results return as Pandas
DataFrames, Polars relations, or Apache Arrow tables, immediately
ready for biostatistics and machine-learning pipelines.</li>
<li class=""><strong>In-browser &amp; zero-egress deployment (WASM)</strong> — compiles directly to
WebAssembly via DuckDB-WASM and Pyodide. Run clinical reasoning 100%
client-side inside SMART on FHIR browser applications — zero PHI ever
leaves the user's computer.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="architectural--standards-matrix">Architectural &amp; Standards Matrix<a href="https://fhir4ds.com/blog/fhir4ds-solution-brief/#architectural--standards-matrix" class="hash-link" aria-label="Direct link to Architectural &amp; Standards Matrix" title="Direct link to Architectural &amp; Standards Matrix" translate="no">​</a></h2>
<table><thead><tr><th>Dimension</th><th>Traditional clinical engines / warehouses</th><th>FHIR4DS (SQL-native engine)</th></tr></thead><tbody><tr><td>Standards compliance</td><td>Fragmented across separate tools</td><td>100% compliant: CQL, FHIRPath &amp; SQL-on-FHIR v2</td></tr><tr><td>Flattening mechanism</td><td>Custom proprietary scripts / ETL staging</td><td>Standardized SQL-on-FHIR ViewDefinitions</td></tr><tr><td>OMOP CDM integration</td><td>Multi-stage offline batch ETL jobs</td><td>Query-time view mapping with standard vocabularies</td></tr><tr><td>Data storage &amp; ingestion</td><td>Requires pre-flattened relational DB</td><td>Zero-ETL on raw JSON, Parquet &amp; live DBs</td></tr><tr><td>Runtime footprint</td><td>Dedicated servers, Docker &amp; heavy runtimes</td><td>Zero-server (Python &amp; browser WASM)</td></tr><tr><td>Evidence &amp; audit trail</td><td>Opaque summary counts &amp; black-box logs</td><td>Traceable logic trails &amp; clinical narratives</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tailored-informatics-applications--workflows">Tailored Informatics Applications &amp; Workflows<a href="https://fhir4ds.com/blog/fhir4ds-solution-brief/#tailored-informatics-applications--workflows" class="hash-link" aria-label="Direct link to Tailored Informatics Applications &amp; Workflows" title="Direct link to Tailored Informatics Applications &amp; Workflows" translate="no">​</a></h2>
<ol>
<li class=""><strong>Query-Time OMOP CDM v5.5 Harmonization</strong> — bridges clinical care to
observational research. Maps FHIR data to standardized OMOP CDM v5.5
tables on-the-fly, resolving clinical concepts across standard coding
systems at query time without offline ETL pipelines.</li>
<li class=""><strong>Computable Guidelines &amp; Phenotyping (CQL)</strong> — express clinical logic
in interoperable CQL and evaluate it directly across longitudinal
data inside your analysis notebook.</li>
<li class=""><strong>Zero-Egress SMART on FHIR Apps (WASM)</strong> — clinical reasoning 100%
client-side in the browser via DuckDB-WASM. SMART on FHIR tools
perform risk scores and guideline matching without transmitting
sensitive patient records to external servers.</li>
<li class=""><strong>Terminology, Auto-Coding &amp; Notes Pipeline</strong> — maps codes between
code systems, automatically resolves free text to standard codes, and
derives structured Condition resources directly from clinical
progress notes.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-performance-behind-query-time-omop">The performance behind query-time OMOP<a href="https://fhir4ds.com/blog/fhir4ds-solution-brief/#the-performance-behind-query-time-omop" class="hash-link" aria-label="Direct link to The performance behind query-time OMOP" title="Direct link to The performance behind query-time OMOP" translate="no">​</a></h3>
<p>The query-time mapping is practical because the projections ride the same
vectorized engine. We benchmarked the <strong>SQL-on-FHIR OMOP views themselves</strong>
on synthetic FHIR R4 (Synthea) at 1k → 10k → 100k patients — roughly 820
FHIR resources per patient, 0.9 GB → 81 GB of raw JSON — materializing the
full OMOP CDM v5.5 table set (person through death, via ViewDefinitions
and the composition SQLQueries) on a single workstation (13th-gen Intel
Core i9-13900KF, 32 threads, DuckDB capped at an 8 GB working set).
Timings are exec-only, median of 3, forced full evaluation:</p>
<table><thead><tr><th>Patients</th><th>FHIR resources (JSON)</th><th>CDM rows materialized</th><th>Total exec</th><th>Peak RSS</th></tr></thead><tbody><tr><td>1,000</td><td>876,903 (0.9 GB)</td><td>876,490</td><td>205 s</td><td>1.2 GB</td></tr><tr><td>10,000</td><td>8.1 M (8 GB)</td><td>8.1 M</td><td>269 s</td><td>3.1 GB</td></tr><tr><td>100,000</td><td>82.1 M (81 GB)</td><td>82.1 M</td><td>35 min</td><td>8.7 GB</td></tr></tbody></table>
<p>The scaling is the story: <strong>100× the patients costs ~10× the time</strong> —
per-patient materialization cost drops roughly 10× with scale, because a
ViewDefinition compiles to columnar SQL whose cost tracks the scan, not
per-record transformation. A representative composition query
(drug-exposure across the 5 source resources) runs in 282 s at the 100k
rung, producing 7.7 M rows under the same 8 GB cap. Nothing is staged,
copied, or synchronized ahead of time — the artifacts are the small,
versioned ViewDefinition + SQLQuery files, and the engine treats them as
queries (full methodology in <code>benchmarks/</code> in the repository).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="licensing--community-collaboration">Licensing &amp; Community Collaboration<a href="https://fhir4ds.com/blog/fhir4ds-solution-brief/#licensing--community-collaboration" class="hash-link" aria-label="Direct link to Licensing &amp; Community Collaboration" title="Direct link to Licensing &amp; Community Collaboration" translate="no">​</a></h2>
<p>FHIR4DS supports both open academic science and enterprise software
environments:</p>
<ul>
<li class=""><strong>Open-source (AGPL-3.0)</strong> — freely accessible for academic medical
centers, informatics departments, grant research, and open-science
evaluations.</li>
<li class=""><strong>Commercial Enterprise License</strong> — tailored for health tech
companies, EHR integration partners, and health systems requiring
proprietary embedding, priority support, and high-performance C++
extensions.</li>
</ul>
<p>Install via <code>pip install fhir4ds-v2</code> · Interactive demos at
<a href="https://fhir4ds.com/" target="_blank" rel="noopener noreferrer" class="">fhir4ds.com</a> · Academic &amp; commercial inquiries:
<a href="mailto:contact@fhir4ds.com" target="_blank" rel="noopener noreferrer" class="">contact@fhir4ds.com</a></p>]]></content:encoded>
            <category>FHIR</category>
            <category>cql</category>
            <category>SQL-on-FHIR</category>
            <category>OMOP</category>
            <category>Analytics</category>
        </item>
    </channel>
</rss>