SQL on FHIR WG Meetings




SQL on FHIR WG Meeting — November 11, 2025
Arjun Sanyal
Principal Antidote Solutions
Nikolai Ryzhikov
CTO at Health Samurai
John Grimes
Principal Research Consultant CSIRO
Gino Canessa
Principal Software Engineer at Microsoft
Kseniia Nikolaienko
AI Lead and Product Manager at Edenlab
Nov 11, 2025
Topics discussed:
- Gino's argument is that an HTTP status is, by definition, the status of the request you just made. You can't use it to report the status of some other job without breaking what HTTP status means. And it bites in practice: some companies write service agreements around how many HTTP errors an interface may return over a period, so a batch of failed jobs, each polled a few times, pushes the API out of SLA and raises customer incidents — even though nothing at all is wrong with the polling. The shape of the fix: the poll returns 200, and the body says the job failed, typically as an OperationOutcome.
- Where the async draft landed this week: Josh explained the microservice architecture behind it, agreed to replace the 200-plus-location with a 303 redirect for successful polling, and it's accepted that a server which already has the answer may just return 200. Errors are still open. Gino noted the bulk spec hit the same fork and proposed two modes — keep the technically incorrect behaviour because it's what's in production today, and add the correct one, with some way for the server to say which it does.
- Table names collide, and nothing stops them. Gino's example: a library holding queries has to name the tables it queries and link those names back to ViewDefinitions — but you may have a FHIR patient view and an OMOP patient view loaded at once, and the odds of everyone prefixing everything appropriately are, in his words, zero. John's diagnosis was that the problem isn't using
name, it's that nothing enforces uniqueness — same as writing two value sets into a terminology server under the same URL, where someone has to complain either at write time or at reference time. The candidates pulled different ways: Nikolai pointed out that in FHIR's canonical resources the technical name iscode, notname— SearchParameter works that way, and a server is even allowed to change it when mounting — while John preferred an optional namespace element used like a SQL schema, so US Core views and OMOP views can be grouped and qualified without people quietly inventing conventions inside the name. Gino's requirement throughout: whatever it is has to disambiguate back to a full canonical URL plus version, since you obviously can't put that URL in the SQL. - John asked how you get a consistent export of several ViewDefinitions — patients, encounters, observations — such that you can actually join the results. Nikolai's answer: not every implementation can promise it. If you send multiple views in one export operation, an implementation that can do it should; send separate requests and you get nothing. Postgres gives it to you through snapshots, Oracle maybe via a long transaction that hurts everything else, and nobody actually knows whether Epic's bulk export is a snapshot. Arjun floated a flag for intent plus some feedback from the server about what you got. It lands on should, not shall.
- Kseniia Nikolaienko demoed Edenlab's analytics work, opening with the caveat that it's analytics on FHIR but not SQL on FHIR — not yet. They hang change data capture off the historisation pipeline they already had, feeding MongoDB into ClickHouse, then put a semantic layer over the views exposing a JSON query language that's much simpler than SQL, which drives both a drag-and-drop BI interface and LLM chatbots. An event abstraction unifies resources so they can compute OMOP-style eras and apply Allen's interval operators — the demo query found patients with no colonoscopy in the last five years. Flattening is done with Liquid templates; they're considering ViewDefinitions but find FHIRPath incomplete for it. Nikolai's challenge was whether a new JSON query language is reinventing SQL, and where CQL fits.