SQL on FHIR WG Meetings

Splitting $run from $evaluate, and why FHIR versions can't be mapped mechanically — Apr 4, 2025

Apr 4, 2025

Reference server growing a small UI

Browse the CapabilityStatement, list ViewDefinitions, run one, switch the output format. $run is an instance-level operation on a ViewDefinition already on the server, aimed mainly at debugging.

$run vs $evaluate — splitting won

Many production servers won't let users create their own ViewDefinitions — it's an administrative or developer function — so it's cleaner to say a stateless service supports one and a managed server the other, than to have a single operation that may or may not accept an inline body and leave people to work that out from errors.

Overloading would also mean expressing at least one of these must be present, and OperationDefinition has no FHIRPath invariants to say it — that's reinventing profiling.

Output formats bind to a group-defined ValueSet

Since Parquet and friends aren't in an existing one.

The binding can't be extensible in any useful way, though: there's no way today for a server to advertise the extra formats it has plugged in. R6's additionalBinding would help and should be added to OperationDefinition too — a ticket was filed during the call — while older versions would need a cross-version extension.

Cross-version mapping — the honest limits

Value set and structure comparisons across R2 to R5 are nearly ready, but the honest finding: some mappings can't be mechanical.

  • R4 Encounter.status finished maps to both discharged and completed in R5 — the map exists, but nothing can tell you which is right without knowing what the site meant, and some of it depends on elements R6 added
  • Other things aren't representable at all: a cross-version extension can't carry a resource, so an element holding OperationOutcomes has nowhere to go

100% coverage was explicitly not the goal, and the limits are being documented as they're hit.

A public FHIR package registry with proper dependency resolution

Mirroring the existing one but served almost entirely from a storage bucket — so no rate limits — with every canonical also loaded into Postgres and searchable by URL prefix.

Its practical point: it implements the npm dependency-resolution API properly. Today an npm install of a package with dependencies doesn't resolve them, which is why a ballot IG with a very large dependency can't simply be installed.