Profiles and ValueSets in FHIR

I’ve been meaning to talk about Profiles and ValueSets for a little while now. They’ve come up from time to time in this blog – this post was a comment from Grahame about the use of Profiles for specific Use Cases, and we’ve have a number of discussions about extensions such as this one which are defined in profiles.

Profiles are actually a ‘big thing’ for FHIR. You can think of the base FHIR structures (Resources, Extensions, Bundles, Tags, Queries etc.) as the common building blocks that you can use to build a solution – the Profile is where you can say how these blocks are used in your particular application – and what are the extra data items (represented as extensions) that you need.  And this can be both computable and as documentation for humans.

Update: Rene Spronk has commented about a video tutorial given by Ewout Kramer that can be found here. This gives a nice overview of profiles and is well worth a read…

Before we get into too much detail, lets talk about a couple of related resources – Conformance and ValueSet.

Conformance

The Conformance resource is used to describe the capabilities of a particular server. This can either be about an actual server (it can be downloaded by a query to the server root like this: http://fhir.healthintersections.com.au/open/metadata – or using the OPTIONS verb) or it can be used when creating specifications for a server – what a client expects a server to be able to do.

As well as specifying the ‘standard’ resources and queries, the conformance resource can reference the profiles that it supports.

Suppose, for example, that we defined a profile for an antenatal visit. The profile might specify:

  • a particular Questionnaire resource (questionnaire.name / questionnaire.identifier)
  • that the questionnaire author must be a Practitioner
  • that the subject is required and so forth

(we’ll talk about how to do this later). We’ll give this profile an identifier that we’ll call ‘antenatal’ in this post.

A server that supported this profile – i.e. it could check that a particular questionnaire had the right identifier, has a subject and a Practitioner author etc. would then add this profile to its conformance statement – if it receives a questionnaire claiming to conform to the antenatal profile, then the server can check that it does – rejecting it if not (and ideally including an OperationOutcome in its response to say why it failed.) Actually – to be correct the spec doesn’t state that the resource should be rejected – that’s up to the implementation to decide.

Now suppose that we have a client application that can create a questionnaire that conforms to this profile. All it needs to do is to POST the questionnaire to the servers Questionnaire endpoint, including a profile tag HTTP Header in the request that contains the antenatal profile. The server recognizes the tag, loads the profile and checks that the submitted resource does, in fact, meet the requirements of the profile. (Again, the details of this are up to the implementation)

In this way, the server can apply business level validation to resources to ensure compliance with business rules.

Finally, a single server can support multiple profiles (Indeed, a single resource could also be compliant with multiple profiles).

ValueSet

A ValueSet is simply a set of codes. It is used where you want to specify that the value for a particular code in a resource is drawn from a pre-defined set of codes. (It can get quite  a lot more complex than that of course, but that description will do for now)

For example, suppose we are recording medicationAdministrations, and want to be able to indicate whether a particular administration was given on time, was early or was late. MedicationAdministration does not have this property so we create an extension definition (in a profile) to represent it. We actually have 2 steps to do in setting this up.

  • First, we create the ValueSet resource. In this case we’ll define the values directly in the ValueSet (we could also refer terminologies like SNOMED or LOINC if that were appropriate) and give it an appropriate identifier. Here is what it might look like
<ValueSet xmlns="http://hl7.org/fhir">
     <identifier value="onTimeOrNot"/>
     <name value="medsontime"/>
     <description value="Were medications given on time"/>
     <status value="draft"/>
     <!-- Define the  options in the resource rather than an external terminology-->
     <define>
         <system value="http://fhir.orionhealth.com/fhir/ns/onTimeOrNot"/>
         <concept>
             <code value='early'/>
             <display value="Early"/>
             <definition value="The medication was given early"/>
         </concept>
         <concept>
             <code value='on-time'/>
             <display value="Early"/>
             <definition value="The medication was given on time"/>
         </concept>
         <concept>
             <code value='ate'/>
             <display value="Late"/>
             <definition value="The medication was given late"/>
         </concept>
     </define>
 </ValueSet>

  • Next we create a profile with an ID of ‘medadmin’ (so we can easily refer to it in a URL) and in that profile we’ll create an extension definition (ExtensionDef). We’ll give the extension a code of ‘onTimeOrNot’. In the definition of the extension we indicate that the datatype of the extension is a code, and that the value of this code must come from the ValueSet we just created (this is called a binding) – by including a reference to the ValueSet in the extensionDef element. Here’s an example (assuming that the ID of the ValueSet was 100):
<extensionDefn>
     <code value="onTimeOrNot"></code>
     <contextType value="resource"/>
     <context value="MedicationAdministration"/>
     <definition>
         <short value="Was the medication given on time"/>
         <formal value="Was the medication given on time"/>
         <min value="0"/>
         <max value="1"/>
         <type>
             <code value="code"/>
         </type>
         <isModifier value="false"/>
         <binding>
             <name value="Set of coded values"/>
             <isExtensible value="false"/>
             <referenceResource>
                 <reference value= "http://fhir.orionhealth.com/fhir/ValueSet/100"/>
             </referenceResource>
         </binding>
     </definition>
 </extensionDefn>

Both resources get saved on our (or someone else’s) server.

When we want to create a MedicationAdministration resource that can record whether the medication was given on time, we simply include an extension in the resource like so:

<extension>
  <url value = 'http://myserver/profiles/medadmin#onTimeOrNot'/>
  <valueCode value = 'early'/>
</extension>

(If we need to, we can GET the profile, then GET the ValueSet to display a list to the user – though we’ll often have that in our application anyway).

If a recipient receives our resource and doesn’t know what ‘onTimeOrNot’ means, they can follow the url to the Profile which will describe the extension, and to the ValueSet which has the options. Of course, as this was an ‘ordinary’ extension we can safely ignore it if we don’t understand it – had it been a modifierExtension then it wouldn’t have been safe to do so.

The following diagram shows the relationships between these resources and note that they are all ‘instance’ resources with a ID – an fact the Profile & ValueSet resources could form the basis for a registry…

profile-1 (1)

Profile

So we’re now ready to start talking about the Profile – and we’ve pretty much used up the space. Just a summary then, and the next post will go into more detail.

  • The profile is how you ‘constrain’ one or more resources to meet your particular Use Case.
  • It is also where you define the extensions you are going to need (and you almost certainly will need some).
  • You can also define custom queries here
  • It contains both computable artifacts and human documentation.
  • It can get complex! – for example one profile can refer to another

One last thing to point out is what profiles can’t do, and that is to change a resource in such a way that a recipient must understand the profile to safely process the resource. This is an absolute no-no in FHIR. For example, you can’t specify a default in a profile, or require the recipient to download the profile before processing.

If you do need to specify something that must be understood then create an extension setting the ‘isModifier’ to true. A resource instance will use the modifierExtension element to hold this data – and a FHIR recipient must always understand modifierExtensions to safely process resources.

About David Hay
I'm an independent contractor working with a number of Organizations in the health IT space. I'm an HL7 Fellow, Chair Emeritus of HL7 New Zealand and a co-chair of the FHIR Management Group. I have a keen interest in health IT, especially health interoperability with HL7 and the FHIR standard. I'm the author of a FHIR training and design tool - clinFHIR - which is sponsored by InterSystems Ltd.

5 Responses to Profiles and ValueSets in FHIR

  1. Rene Spronk says:

    For a video tutorial about FHIR profiles, see

    – this doesn’t cover profiling valuesets, but it does provide an overview of profiling.

  2. A few clarifications. First, Conformance isn’t only used to document the capabilities of a server. Conformance is used to document the FHIR capabilities of any system – client, server or other. If you don’t have a Conformance instance for a system, you can’t claim to be FHIR conformant. The only thing special about RESTful servers is that they must make the Conformance resource instance from a specific end-point. How other systems make their Conformance instance available to interested parties is up to them.

    Second, Conformance isn’t *only* used to document the capabilities of systems (i.e. a specific configuration of software operating at a specific network location). It can also be used to document the general capabilities of a product that could be installed in multiple locations (i.e. what can software vendor ABC’s XYZ application do?). Finally, it can be used to document desired system capabilities, for example for use in an RFP.

    Third, your diagram may be a bit misleading, as the Conformance, Profile and ValueSet resources displayed are also resource instances. And in fact, you can have Profiles that constrain Profiles and Conformance and ValueSet resources too . . .

    • David Hay says:

      Hi Lloyd,

      Thanks for that – not the clearest of posts I must admit on re-reading…

      I’ve altered the diagram with a title of ‘Definition’ rather than ‘Design Time’ – hopefully that will be a bit more clear…

  3. Pingback: FHIR Medication lists revisited | Hay on FHIR

Leave a Reply

Discover more from Hay on FHIR

Subscribe now to keep reading and get access to the full archive.

Continue reading