FHIR servers compared: HAPI FHIR, Medplum, AWS HealthLake, Azure Health Data Services, Google Cloud and Firely
How the main FHIR servers differ on licence, FHIR versions, persistence, SMART on FHIR, Bulk Data, Subscriptions, validation and EU hosting, with a selection guide by scenario.
Ala Ben Aicha

Direct answer
Pick a FHIR server by asking three questions in order: where must the data live, which FHIR version and implementation guides must you serve, and who will operate the database at 3 a.m. For a self-hosted open-source server, HAPI FHIR (Java) and Medplum (TypeScript) are the two serious options, both Apache 2.0. For a managed service, AWS HealthLake, the Azure Health Data Services FHIR service and the Google Cloud Healthcare API cover R4 well but each leaves gaps you fill yourself. Firely Server, Aidbox and InterSystems IRIS for Health are commercial products for teams that want vendor support and multi-version or profile-heavy deployments.
What a FHIR server actually does
A FHIR server is a database plus a REST API that speaks the HL7 FHIR resource model: create, read, update, search, history, transactions, and a CapabilityStatement at /metadata that declares what it supports. That last point matters more than any vendor page. Two products can both say "FHIR R4" and still differ on chained search, _include, conditional updates, transaction bundles or which operations exist.
People searching for a "FHIR database" usually want the same thing: a store whose native shape is FHIR JSON, indexed for FHIR search. Underneath, every product here uses an ordinary database (PostgreSQL, SQL Server, Oracle, MongoDB or a cloud-managed store). The FHIR layer is the index, the search engine, the validation and the security model on top. If you are new to the API itself, start with the FHIR integration guide.
The comparison table
Facts below were checked against vendor documentation on 6 October 2026. Re-check the CapabilityStatement of the exact version you deploy.
| Server | Licence / model | FHIR versions | Persistence | SMART on FHIR | Bulk $export |
|---|---|---|---|---|---|
| HAPI FHIR (JPA server) | Apache 2.0, self-hosted | DSTU2, DSTU3, R4, R4B, R5 (one per server instance) | PostgreSQL, SQL Server, Oracle; CockroachDB experimental | Not built in; you put an OAuth server in front and enforce with interceptors | Yes, off by default in the starter project |
| Medplum | Apache 2.0, self-hosted or Medplum's hosted service | R4 | PostgreSQL | Yes (built-in auth, SMART App Launch) | Yes, Bulk Data 2.0.0 |
| Firely Server | Commercial; evaluation licence and public sandbox | STU3, R4, R5 | SQLite (default), SQL Server, MongoDB | Via Firely Auth | Via the Bulk Data Export plugin |
| Aidbox | Commercial; free development licence (no PHI, 5 GB cap) | STU3, R4, R4B, R5, R6 ballot | PostgreSQL (JSONB) | Yes (SMART App Launch 2.0.0) | Yes (Bulk Data 2.0.0) |
| InterSystems IRIS for Health | Commercial; self-hosted or InterSystems cloud | STU3, R4, R5 | IRIS | Yes | Yes, via the Bulk FHIR Coordinator (2023.1+) |
| AWS HealthLake | Managed, HIPAA eligible | R4 only | AWS-managed | Yes | Yes, plus S3 import |
| Azure Health Data Services FHIR service | Managed | R4 (4.0.1), STU3 (3.0.2) | Azure-managed | Yes, Microsoft Entra ID | Yes, plus $import |
| Google Cloud Healthcare API | Managed | DSTU2, STU3, R4, R5 | Google-managed | Yes, via SMARTProxy and your own auth server | Store export to Cloud Storage or BigQuery, not the Bulk Data spec |
Self-hosted open source: HAPI FHIR and Medplum
HAPI FHIR is the long-standing open-source Java implementation of FHIR, covering the data model, client, validator and a full JPA server. The JPA server runs on PostgreSQL, SQL Server or Oracle; MySQL and MariaDB are deprecated for performance reasons. The Instance Validator checks resources against StructureDefinitions and can load implementation guide packages, which is what you need for US Core, EU or national profiles. Subscriptions support rest-hook, websocket and email channels.
What HAPI does not give you is an identity provider. Its security documentation is explicit that it provides building blocks (authorization, consent and search-narrowing interceptors) rather than one security layer. In practice you pair it with Keycloak or a cloud identity service and map SMART scopes to interceptor rules yourself. HAPI is maintained by Smile Digital Health, which sells Smile CDR as the commercial, supported distribution.
Medplum is a TypeScript monorepo under Apache 2.0: a FHIR R4 datastore on PostgreSQL, built-in OAuth/OpenID/SMART auth, Subscriptions, server-side "Bots", a TypeScript SDK and React components. It supports Bulk FHIR 2.0.0 at /fhir/R4/$export. It is closer to an application platform than a bare server, which is why product teams building a care app or a custom EHR tend to like it. The trade-off: R4 only, and you adopt its project and access-policy model.
Commercial servers: Firely, Aidbox, InterSystems
Firely Server (.NET) can expose STU3, R4 and R5 endpoints, runs on SQL Server or MongoDB for production, and ships Firely Auth for SMART, a Bulk Data Export plugin, a mass-ingest tool and profile validation. It is a natural fit when profile conformance is the product, for example national IG work. You can trial it on the public sandbox or an evaluation licence; production needs a commercial licence.
Aidbox stores resources as PostgreSQL JSONB, which gives you SQL access to FHIR data next to the FHIR API. The development licence is free but forbids real patient data and caps the database at 5 GB; production use needs a paid licence.
InterSystems IRIS for Health bundles a FHIR server (STU3, R4, R5) with SMART support, bulk FHIR exchange and a profile validator inside the same platform that runs HealthShare and many hospital integration engines. If an establishment already runs IRIS, adding its FHIR repository is often simpler than introducing a new stack.
Managed cloud: HealthLake, Azure, Google
AWS HealthLake is FHIR R4 only. It offers SMART App Launch, Bulk Data export, bulk import from S3, integrated medical NLP that writes extracted entities back as FHIR resources, SQL access via Athena, and a Data Transformation Agent (preview) for C-CDA and CSV. Watch the quotas: 500 resources per Bundle, one concurrent import job and one concurrent export job per Region.
The Azure Health Data Services FHIR service supports R4 4.0.1 and STU3 3.0.2, transactions, $export, $import, $validate against profiles and $convert-data for HL7 v2 and C-CDA conversion, with SMART scopes on Microsoft Entra ID. The older Azure API for FHIR reached its retirement date on 30 September 2026; if you still run it, you are on an extension request and should be mid-migration.
The Google Cloud Healthcare API supports DSTU2, STU3, R4 and R5 stores, enforces profiles and implementation guides on write, and streams changes to Pub/Sub and BigQuery. Its conformance statement is honest about the gaps: the store export is a whole-store dump, "not an implementation of the FHIR Bulk Data" specification, and Pub/Sub notifications are not FHIR Subscriptions. SMART on FHIR works through the open-source SMARTProxy with an authorization server you run.
The features that decide projects
| Need | What to check | Who covers it best out of the box |
|---|---|---|
| Patient or clinician apps | SMART App Launch (current STU 2.2), .well-known/smart-configuration, scope enforcement |
Medplum, Firely, Aidbox, IRIS, HealthLake, Azure |
| Population export | Bulk Data Access (STU 3 published Dec 2025; STU 2 clients still work) with Group-level $export |
HAPI, Medplum, Firely, Aidbox, HealthLake, Azure |
| Event-driven integration | R4 Subscriptions Backport or R5 topic-based subscriptions | HAPI, Medplum, Aidbox, HealthLake; Google uses Pub/Sub instead |
| Profile conformance | $validate, IG package loading, rejection on write |
HAPI, Firely, Aidbox, Google, Azure |
| Terminology | $expand, $lookup, $validate-code on large code systems |
HAPI and the commercial servers; managed clouds are thin here, so plan an external terminology server |
Before shortlisting, run the same probe against every candidate:
curl -s https://fhir.example.org/fhir/metadata \
| jq '{version: .fhirVersion, ops: [.rest[0].operation[]?.name], types: [.rest[0].resource[].type] | length}'
curl -s https://fhir.example.org/fhir/.well-known/smart-configuration | jq '.capabilities'
Then test one real search you will need in production, for example a chained search on Observation?patient.identifier= with _include, and one transaction bundle of your real size. Most surprises show up there, not in the feature matrix. SMART specifics are in the SMART App Launch guide.
EU data residency
Hosting location is a regulatory input, not a preference. Current regional options:
- Azure FHIR service: France Central, Germany West Central, North Europe, West Europe, Sweden Central, Switzerland North, UK South and UK West, per the regional availability table. The same table shows the Events feature is not listed for those European regions, which affects event-driven designs.
- Google Cloud Healthcare API: europe-north1, europe-west2, europe-west3, europe-west4, europe-west6, plus an
eumulti-region, per its locations page. - AWS HealthLake: Europe (Ireland) and Europe (London) only; no continental EU Region at the time of writing.
- Self-hosted (HAPI, Medplum, Firely, Aidbox, IRIS): wherever you deploy them, including a certified French HDS host or a hospital data centre.
Region choice does not settle transfer questions under GDPR or national hosting rules by itself, and some national programmes require certified hosting. For the EU interoperability side, see FHIR EU Core and EHDS implementation.
Selection guide by scenario
| Scenario | Shortlist | Why |
|---|---|---|
| Startup MVP, small team, app-first | Medplum, or HealthLake / Azure if you are already on that cloud | Auth and SMART included; no database tuning in year one |
| Hospital integration hub | HAPI FHIR or IRIS for Health behind an interface engine | Full control of profiles, terminology and local search parameters; HL7 v2 stays in the engine (see interface engines compared) |
| Analytics and research | Any server with Bulk $export, then a separate analytics store |
A FHIR server is a poor warehouse; export to Parquet or OMOP (see FHIR to OMOP) |
| Regulated EU deployment | Azure FHIR service in an EU region, Google in eu, or self-hosted HAPI / Firely / Aidbox on certified hosting |
Residency, national IG validation and audit logging decide it |
| Multi-version or national IG publisher work | Firely, Aidbox, HAPI | STU3/R4/R5 side by side and strong validation |
Pitfalls seen in practice
- Treating the FHIR server as the integration engine. It stores and serves resources. Routing, HL7 v2 parsing, retries and mapping belong elsewhere.
- Assuming "supports R4" means your queries work. Chained search,
_has,_includedepth and paging differ. Test with production-sized data. - Skipping the terminology plan. Validation against EU or national profiles needs SNOMED CT, LOINC and local value sets loaded somewhere.
- Locking into proprietary extras early. NLP, Bots, JSONB SQL and Pub/Sub are useful; keep your core contract on standard FHIR so a migration stays possible. Azure API for FHIR customers just learned why.
- Ignoring export limits. One concurrent export job per Region on HealthLake changes how you design nightly analytics.
If you are choosing or migrating a FHIR server and want an independent read of the trade-offs, that is part of HL7 FHIR integration work.