Extensions
The FHIR model is designed to meet core requirements for everyone from small independent veterinary clinics to giant healthcare systems. By only including only the details that are relevant for most use cases, the FHIR model is simpler than it would be if it tried to accommodate every use case.
In order to support the requirements that make your use case unique, FHIR provides the ability to extend every FHIR resource to store additional data.
Storing your data natively in the FHIR model makes it possible to share that data with other FHIR services easily. Extensions should be used only when there is no other way to store your data in the FHIR model. In our experience, you can generally fit 80-90% of their data into the FHIR store natively.
Anatomy of an Extension
The FHIR specification includes example Extensions in the documentation for each resource. For example, Patient resource extension examples are available here (opens in a new tab). One of the simplest extensions listed there is the 'mothersMaidenName' extension (opens in a new tab) which adds a string value to the Patient resource to hold the Patient's mother's maiden name.
If the Patient's mother's maiden name were 'Smith', the extension would be represented on a FHIR Patient resource as:
{
"resourceType": "Patient",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-mothersMaidenName",
"valueString": "Smith"
}
]
}
- The
extension
property is an array of Extension elements (opens in a new tab). - Each Extension element has a
url
property that uniquely identifies the extension. This URL is used to look up the StructureDefinition (opens in a new tab) resource that defines what the extension is for and how it should be used. - In this case, the
valueString
property holds a string value for the extension. However, the key to extensions is that you can store any kind of value here because this field conforms to the "Choice of Data Types" pattern (opens in a new tab). For example, you could store an integer asvalueInteger
or a date asvalueDate
.
If you need to store a piece of data that doesn't fit natively in the FHIR specification take a look at the FHIR specification extension examples before doing the work of creating your own extension. You may find that the extension you need already exists.
Nested Extensions
Extensions can have extensions of their own. This allows for storing a number of related values in a single top-level extension to relate them.
Because the top-level extension url
property points to the StructureDefinition which defines how the nested extensions should be used, nested extensions may use relative URLs for their url
property. There is no need to define a new StructureDefinition for each nested extension.
Creating an Extension
Making your own extension is a two step process:
- Choose a canonical URL for your extension.
- Add the extension to a FHIR resource using the
extension
property.
Extension Canonical URL
The canonical URL is a globally unique absolute URL that you control. For example, it might look like: https://extensions.yourdomain.com/really-cool-extension
.
Ideally, you should author and publish a StructureDefinition (opens in a new tab) resource that defines the extension as encouraged by the FHIR specification. The StructureDefinition resource describes the purpose of the extension, and the structure of the data in the extension so that anyone who comes across the extension can visit the canonical URL to understand what the extension is for and how to use it.
In reality, it's a good deal of effort to create, publish, and maintain these StructureDefinition resources, especially during early development phases where they may be in flux. So, it's not uncommon for developers building on FHIR to maintain simpler internal documentation for extensions that they don't intend to share with the world. As long as you're careful to choose a canonical URL that is on a domain that you control, you can always publish a proper StructureDefinition there if it ever becomes necessary.
Add the Extension to a FHIR Resource
Imagine you have a patient application which Patient Users log into to schedule appointments and check lab results. In this app, you might have some nice UI features like a dark mode / light mode toggle, and a notifications toggle. You want to store the Patient's selections for these features so that you can use them to customize the Patient's experience when they log in.
First, you choose the URLs for your extension. You might choose: https://extensions.yourdomain.com/patient-app-preferences
for the top-level extension, and dark-mode
and notifications-enabled
for the nested extensions.
Then, you can add the extension to a Patient's resource when you know their preferences. To make it easier for you to try it out, the example creates a new Patient with the extension, but you can add the extension to an existing Patient resource as well using Update.
Create a FHIR Patient with the https://extensions.yourdomain.com/patient-app-preferences
extension using the v3 SDK:
import { Patient } from 'fhir/r4b'; // npm install @types/fhir
import Oystehr from '@oystehr/sdk'
const oystehr = new Oystehr({
accessToken: "<your_access_token>",
});
const createdResource/*: Patient*/ = await oystehr.fhir.create<Patient>({
resourceType: 'Patient',
active: true,
name: [
{
given: ['Jon'],
family: 'Snow',
},
],
address: [
{
use: 'home',
type: 'physical',
text: 'Winterfell',
},
],
extension: [
{
url: 'https://extensions.yourdomain.com/patient-app-preferences',
extension: [
{
url: 'dark-mode',
valueBoolean: true,
},
{
url: 'notifications-enabled',
valueBoolean: false,
},
],
},
]
});
Additional Resources
- Before making an extension, consider searching on the FHIR chat (opens in a new tab) to see if there are discussions about modeling for your use case.
- Connect with us in the Oystehr Slack Workspace (opens in a new tab) for help finding the right place to fit your data into the FHIR model.