FHIR versions in 2026 and 2027
Choose the right FHIR version for new integration projects - build on R4 today and plan a configuration-only move to R6.
New FHIR projects in 2026 face a version decision that will outlive them: R4, R4B, R5 or the upcoming R6. We recommend building on R4 now and architecting so that moving to R6 later is a configuration change, not a rewrite.
R4 now, R6 next
R4 is the most widely deployed version in production. In the 2025 State of FHIR survey, 40% of national-level respondents rated R4 their main standard, while R4B and R5 scored 3% each. R4B's changes are confined to medication definition resources for regulatory submissions, and major toolkits treat their own R4B support as experimental. R6 is mid-ballot - its fourth normative ballot draft appeared in August 2026 and HL7 has scheduled the final ballot for 2027 - so production adoption is a 2027 story at the earliest.
For an integration layer, the practical consequence is that services must not hardcode assumptions about the server version. With Zato, the version lives in the connection definition, not in the code - a service asks the server itself:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class ShowFHIRVersion(Service):
name = 'demo.fhir.show-version'
def handle(self) -> 'None':
client = self.fhir['FHIR.Sample']
# The CapabilityStatement describes the server, including its FHIR version
capability = client.execute(path='metadata', method='get')
self.logger.info('Server is on FHIR %s', capability['fhirVersion'])
When the server behind the connection moves from R4 to R6, the connection's address changes in the Dashboard and the services keep running - they depend on the connection name, not on the server version.
US Core has no R5 edition
In the USA, the US Realm Steering Committee voted in September 2025 that US Core will develop only on R4 or R6, with no R5 edition planned. The Argonaut transition strategy is concrete: an R6-based US Core v10 targets May 2027, contingent on R6 clearing its final ballot, and R4 remains supported for 4-6 years after that. The practical consequence is that US-facing integrations written today should use the search parameters that are normative in both R4 and R6, starting with identifier-based lookups:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class FindPatientByMRN(Service):
name = 'demo.fhir.find-patient-by-mrn'
def handle(self) -> 'None':
client = self.fhir['FHIR.Sample']
# Identifier search works the same in R4 and R6
patient = client.resources('Patient').search(identifier='urn:mrn|12345').first()
self.logger.info('Found %s', patient['name'])
EHR vendors stay on R4
Major EHR vendors, including Epic and Oracle Health, do not support R5, and Germany's national profiling guidance likewise advises staying on R4 rather than adopting R5. Connecting to an EHR is the same step regardless of the vendor: an outgoing FHIR connection with an OAuth security definition pointed at the EHR's R4 endpoint, as described in HL7 FHIR security - tokens are obtained and refreshed for you, and the code above works unchanged.
Cloud FHIR service migrations
Azure API for FHIR shuts down on 30 September 2026 in favor of Azure Health Data Services, and AWS HealthLake supports R4 only, so many integrations are moving between FHIR servers in 2026. To move the data, write a service with two connections:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class MigratePatients(Service):
name = 'demo.fhir.migrate-patients'
def handle(self) -> 'None':
source = self.fhir['FHIR.Old']
target = self.fhir['FHIR.New']
# Read pages of patients from the old server ..
for patient in source.resources('Patient').limit(100):
# .. take each one's data without the old server's metadata ..
data = patient.serialize()
if 'meta' in data:
del data['meta']
# .. and write it to the new server.
target.resource('Patient', **data).save()
Terminology moves faster than the spec
The code systems that FHIR resources point at now release faster than FHIR itself: SNOMED CT International publishes monthly, LOINC 2.82 arrived in March 2026 with around 106,000 codes, and ICD-10-CM uses fiscal-year identifiers. Integrations do not parse these releases - they send the codes in searches and the server does the matching:
# Serum sodium observations, by their LOINC code
observations = client.resources('Observation').search(code='http://loinc.org|2951-2')
for observation in observations.fetch():
self.logger.info('Value: %s', observation.get_by_path('valueQuantity.value'))
See also
| Page | What it covers |
|---|---|
| FHIR in Europe | EHDS deadlines and national programs, with code for each |
| Connections | The Dashboard form and everything self.fhir accepts |
| Security | The OAuth setup that EHR endpoints require |
Learn more
Schedule a meaningful demo
Book a demo with an expert who will help you build meaningful systems that match your ambitions
"We evaluated 12 integration platforms and Zato was the only one to score 100%."
Philip Zuñiga, Assistant Professor, University of the Philippines