REST & GraphQL for health data
FHIR is REST-shaped, and REST makes you fetch a patient's chart in fourteen round trips. GraphQL fixes that and brings its own problems — including one that matters specifically in health.
In one line
REST exposes resources at URLs; you fetch them one kind at a time. GraphQL lets the client ask for exactly the shape it wants in one request. FHIR is natively REST and also speaks GraphQL — and the choice has a health-specific catch.
Why REST hurts here
FHIR's REST design is clean and predictable: GET /Patient/123, GET /Observation?patient=123,
GET /MedicationRequest?patient=123. Every resource has a URL, HTTP verbs mean what they mean,
and caching works.
Then you build a patient summary screen. You need the Patient, their Conditions, their MedicationRequests, their AllergyIntolerances, recent Observations, their Encounters, the Practitioner each references, the Organization behind that…
That's a dozen-plus round trips, several of them only discoverable after the previous response came back (you can't fetch the Practitioner until you know which one). On hospital wifi, from a tablet, that's a visibly slow screen — and clinicians measure your software in seconds.
This is the N+1 problem, and in FHIR it's structural rather than accidental: the spec is
deliberately granular, and granularity is what costs you round trips. _include and _revinclude
help, $everything helps, but the shape of the problem remains.
What GraphQL changes
One request, one response, exactly the fields you asked for:
{
Patient(id: "123") {
name { given family }
ConditionList(_reference: patient) { code { text } }
MedicationRequestList(_reference: patient) { medicationCodeableConcept { text } }
}
}
The wins are real: no over-fetching (mobile clients stop downloading fields they discard), no under-fetching (no waterfall), and the client evolves its query without a new endpoint — which matters when the API team and the app team are different organisations on different release cycles.
FHIR has a GraphQL binding, so this isn't exotic. Several servers support it.
What it costs
- Caching mostly dies. HTTP caching is URL-based; GraphQL POSTs everything to
/graphql. You lose CDN and proxy caching and rebuild it in the application, badly. - Arbitrary query cost. A client can request a deeply nested graph that costs the server enormously. You need depth limits and cost analysis, or you've shipped a denial-of-service endpoint with a friendly schema.
- Observability gets harder. Every request is
POST /graphqland a 200. Your logs and metrics stop meaning anything without extra work — and200 OKwith an errors array is GraphQL's normal way of failing, which breaks every alerting rule you had. - Fewer people know it. In health IT, that's a real staffing consideration.
The health-specific catch
Here's the one that isn't in the general GraphQL literature.
Authorisation in health is field-level and contextual, and GraphQL's shape fights that.
With REST, "may this user read Observations for patient 123?" is a question about a URL. You can answer it at the edge, log it, and audit it. With GraphQL, a single request may traverse Patient → Condition → Encounter → Practitioner → Organization, each with different rules — and some fields (psychiatric notes, HIV status, safeguarding flags) carry restrictions the others don't.
Now try to answer "who accessed this patient's mental health data, and when?" — a question you will be asked, by a regulator or a patient. With REST it's a log line. With GraphQL it's a resolver-level audit problem you must have designed for in advance, or the answer is "we don't know."
That's not a reason to avoid GraphQL. It's a reason to decide the audit story before you adopt it, because retrofitting it is very hard and audit logs are not optional in this sector.
The practical read
- REST for interop. It's what FHIR is, what everyone implements, and what SMART authorises against. Your ABDM and US Core work is REST.
- GraphQL for your own front end, over your own gateway, where you control both ends.
- Neither for bulk. Population extracts are Bulk Data — a different tool for a different question.