FHIR XDS: revisiting the patient identity.

While at the HINZ conference this year, I was at dinner with Grahame and ‘Friendly FHIR’ (your identity is safe with me), and we were talking about the roles of the Identity Source and XDS Registry in the context of a FHIR XDS implementation. In previous posts I had indicated that the Identity Source could simply expose a FHIR Patient endpoint – and that is still an option for general use – but in the case of the XDS Registry, Grahame pointed out 2 issues with that approach:

  • If the XDS infrastructure is heavily used, then the load on the Identity Source is going to be high
  • Merged patients are an issue because DocumentReference resources in the registry will continue to have references to patients that have been merged with another and it needs to return all references to all merged patients when responding to a query for a single patient.

So, the registry really does need to maintain it’s own store of patients – though this is really a specialized ‘cache’ that is only updated by the Identity Source. This also means that there is really no need for a Document Consumer to access the Identity Source directly – at least in the XDS context – which is a bonus.

We’ve talked before about how FHIR represents merged patients (Actually, just checking the specs I note that there is now a link type property that must be set to ‘replace’ to indicate the merge), so I won’t repeat that here, but it is worth thinking about how this could all work in the context of an Identity Source needing to update an XDS Registry.

The requirement is that when there are changes to patient information at the identity source, then that needs to be communicated to the XDS registry somehow. We don’t need all the patient details all of the time – the more we store then the greater the volume of updates –  but we probably want the ID, the links, the identifier information and the basic name/Date of Birth/Gender stuff. We would want to be notified about:

  • new patients
  • changes to the patient data we are storing
  • any merges

The XDS registry then needs to maintain an internal data store of some sort that maintains those links between patients so that when a document consumer queries the registry, all the DocumentReference resources for that patient and any patients merged to it are returned as well. (And note that each DocumentReference resource will continue to refer to the Patient it was associated with at creation time – it is the patient that is merged and not the other resources that refer to it).

There are a couple of ways we could do this:

  • Either the Identity Source could push changes to the XDS registry as they occur (a ‘push’ model)
  • Or the Registry could periodically request changes from the Identity Source. (a ‘pull’ model).

Lets consider the push model first.

When the Identity Source merges a patient with another, there are 2 Patient resources to change:

  • The Primary resource (the one you want to keep) has a reference to the secondary resource (that is being replaced) with a link type of ‘replace’.
  • The Secondary resource has a link back to the primary (also with a type of replace) and has it’s ‘active’ property set to false.

As these really need to be managed as a transaction, then the Identity Source places the two resources in a bundle and either:

  • Posts it to the root of the XDS registry
  • Or (and this is probably more explicit) the XDS registry exposes a service (maybe /service/patient/merge) that takes the bundle of resources

In either case, the registry updates its data store. It might return an OperationOutcome resource to indicate the outcome.

So that is the push from the Identity Source to the XDS registry – how would the pull model work?

Well, because FHIR is built using standard internet type technologies, there’s a pre-existing standard that is intended for communicating changes and updates between systems, and that is the Atom feed – which we’ve seen used as the bundling mechanism when we want to move multiple resources around.

In this use, we’re implementing a ‘pub/sub’  architecture where the client (the XDS registry) subscribes to a feed of changes published by the Identity Source. Reviewing the spec, we note that the history operation allows a server to publish changes for a specific resource, a type of resource, or all resources on that server. In our use case, we’d go for the middle option – we want a feed from the Identity Source that publishes all changes for any Patient resource.

So what happens is something like this:

Periodically the XDS registry issues a GET request to the Identity Source like this:

GET /identityServer/Patient/_history?_since=<dateLastQueried>

This will return a bundle containing all the changed resources since the last request. The registry can then process the Patient resources in that bundle and update it’s internal data store as required.

So which pattern to choose? Well, that depends on your implementation.

The ‘classical’ XDS way is the push from Identity Source to Registry, and that is probably the simplest  (though in practice you might want to put an integration engine in the middle so the Identity Source doesn’t need to be concerned with communication issues – and could support other systems that maintain patient caches).

However the pull feed option might be useful if there are multiple clients needing updates, of if that technology is already supplied by the Identity Source.

Hopefully that finishes off XDS stuff for a while, because I’d like to start thinking about FHIR documents…