SQL on FHIR WG Meetings
SQL on FHIR WG Meeting — January 21, 2025
Nikolai Ryzhikov
Nikolai Ryzhikov
CTO at Health Samurai
Dan Gottlieb
Dan Gottlieb
Principal, Data standards Central Square Solutions
John Grimes
John Grimes
Principal Research Consultant CSIRO
Bashir Sadjad
Bashir Sadjad
Software Engineer at Google
Gino Canessa
Gino Canessa
Principal Software Engineer at Microsoft
Jan 21, 2025

Topics discussed:

  • Nikolai opened by proposing they find the atomic operation first — one view, one format, one destination — and compose bulk behaviour on top of it. Gino wasn't convinced: real bulk exports cross resource types while a ViewDefinition only ever covers one, so an atomic-per-view operation would cover too little of the use case, and composing them invites states nobody has thought about. Bashir came at it from cross-references — if an Observation view refers to a Patient view, you need both extracted at the same instant — so a single request has to take several view definitions.
  • Dan's case for splitting: bulk export is one hundred percent download mode, where the server throws the data over the wall and stops caring. Creating a table is a different animal — what if the table already exists, do you clear it, drop and recreate it, add incrementally, and do you need a connection profile for an external database? None of that resembles a format question like Parquet versus NDJSON. The heuristic he offered: if the outputs look different, split the operation; if they overlap, combine. He also expects a legacy EHR to only ever support the file half.
  • Nikolai's counter was that a table target is a useful abstraction precisely because it's declarative: tell the server to keep this view up to date in that table and don't make me think about buckets, files and sync — pipelines do the heavy lifting underneath. Bashir pushed back the other way: export should stay dumb and always hand back file URLs, since whether the bytes live in a file or a database is an implementation detail. Keeping a downstream warehouse in sync is system integration, arguably the client's job — and though maintaining views is one of the main things FHIR Data Pipes does, he wasn't sure it belongs in the FHIR spec at all.
  • The streaming case got trimmed fast. Nikolai's actual use case was debugging — stream a sample of rows into a view builder — and Bashir suggested a count parameter would do the job without dragging a whole streaming mode into the design. Gino said subscriptions can be bolted on later and the framework already copes with non-FHIR events, but warned about scale: implementers rejected the older design because they can't have every client registering views against their database, and a system with a million records could end up carrying millions of materialised views since every app filters differently. Dan's cheaper version — notify that the view changed, let the client re-export with _since, and never ship rows through the notification channel.
  • On how to proceed, John argued for the same reference-implementation-led approach that produced the original spec, and had already started a small JavaScript package over NDJSON files to make the discussion tangible. Dan agreed but wanted the minimum parameter set pinned down first, borrowing names from bulk export and other FHIR operations rather than inventing new ones out of ignorance — which, as he put it, is why you do this as a group, since everybody knows a different corner of FHIR. Gino's version of the same warning: don't recreate parameters that already exist under a different name. The group landed on starting with the file case as the simplest.