In the real world, FHIR servers are not production ready. They may be sold as one-click deployable solutions, but I’ve never seen that work outside a classroom or a hobby project.
In the real world, if you’re building a solution with a FHIR server at its center, you have little choice but to write your own proxy or “Intercept Layer” to sit between the consumer and the server.
For consumers, the Intercept Layer IS the FHIR API.
It may pass on the request to the underlying API and then pass the response back to the consumer unchanged. Or it may take action and modify the request or the response.
Here’s why you might want to build an Intercept Layer.
1. Implement Operations not Supported by your FHIR Server
The list of published FHIR operations is long. The list of operations supported by any one commercial or open source FHIR server is shorter — often far shorter.
If you want to use the patient $match operation, chances are you’ll have to write your own. In some cases even common operations such as ValueSet $expand are not implemented by FHIR servers.
In order to write your own operation you need to control the endpoints. If the consumer calls /ValueSet/$expand, and /ValueSet/ is part of your Intercept Layer, you can build out that $expand operation as required.
If you’re relying on the FHIR server to do all the work, good luck with that support ticket you’ve just opened.
2. Perform Business Validation on Resources
All FHIR servers support validation against the FHIR specification and most support validation against Profiles. Many FHIR SDKs also have validation capabilities.
But your business use case may require validation beyond a resource’s elements. You may wish to query your FHIR server before allowing new Practitioners or Organizations to be created in order to check for duplicates.
Or you may wish to compare the Medication in a specific MedicationRequest against known stocks of that medication before accepting the request.
Every business and organization will have its own custom business rules that require custom validation.
Business validation, not FHIR resource validation.
3. Apply Version Ids to Provenance Resource Targets
A Provenance resource should come with every transaction. Ideally each target element in that Provenance should contain a link to the specific version of the resource that was updated.
The problem is, the app sending the transaction does not know in advance what that version might be.
How do you resolve this?
A Provenance without version specific targets loses much of its value. A “Resolve as version specific” extension does exist and seeks to address this, but I’ve never seen it implemented.
When you intercept all create and update requests, you give yourself the ability to apply correct version references to the Provenance resource after the updates have been performed.
You can do this by implementing the “Resolve as version specific” extension or you can choose to do this unilaterally. I’m in favour of the latter approach.
4. Create AuditEvent Resources for Every Request
Some FHIR servers allow you to configure automated AuditEvent resource creation. But not all. If you’re unlucky enough to be using a FHIR server that does not have this feature, you’ll have to implement it yourself.
With an Intercept Layer in place this becomes trivial. After the request is carried out and before the response is sent back to the consumer, you plug in your own custom code that creates an AuditEvent resource based on the incoming request and on the response body.
5. Block Access to Unsupported Resources
Most managed FHIR servers give you an all encompassing solution. Consumers are faced with 145 accessible resource types and there is no option to “switch off” or disable the ones you don’t use.
Your use case may not require this. But unless you’re building a complete Hospital Information System with a FHIR backend, it’s unlikely you’ll be using every FHIR resource type.
When access to your FHIR server flows through an Intercept Layer, you control which endpoints and resources are exposed.
You may need to intercept and adjust the FHIR server’s CapabilityStatement as part of this process, otherwise there will be a mismatch between what the server says it supports and what it actually supports via your Intercept Layer.
An example of a FHIR resource you may wish to restrict read and write access to is AuditEvent. Depending on your use case there may be others.
6. Enforce Conditional POST and PUT Requests
Duplicate patient data is a real problem. It’s one of the reasons FHIR has a Person resource and one of the reasons the Patient.link element exists.
But these are band aids — they don’t completely fix the problem. This is where custom code enforcing your own business rules comes into play.
As you’re intercepting all incoming requests, you have the power to enforce conditional create and update requests that restrict the ability to create new patients or make changes to existing patients.
You also have to ability to run internal $match operations for the new patient against your FHIR server and take action on the results.
This action may be to reject the request outright or it may be to amend the request — changing a create to an update, or changing the response if a matching resource is found.
This doesn’t only apply to patients. Your data, your rules. That’s the power of building your own Intercept layer.
7. Alter the Request Body Coming In
Business rules and business requirements again come into play here. You may need to make changes to resources before they go into your FHIR server.
Examples include adding Security Labels or Tags to specific resources coming in from identified sources and apps. These labels and tags can be used to help your solution better manage the data from a business perspective.
Areas where this might be required include — but are not limited to — security policies, data retention policies and patient consent.
At a more invasive level, there may be a requirement to anonymize some resources and resource elements before they enter your FHIR server.
8. Alter the Response Body Going Out
Role Based Access Control (RBAC) often needs to be applied in different ways and at different levels. A search Bundle might need to be have resources or elements removed before they are returned to whoever is making the request.
Who has write access to an Organization resource? Who is allowed to read AuditEvents? Does everyone have read access to security labels?
Smart-on-Fhir will only take you so far. Sometimes the requirements move beyond its capabilities, at which point custom code is required to limit access to data that an individual is not allowed to see.
Conclusion
I’d like to reiterate what I said at the beginning. In the real world, FHIR servers are not production ready.
If you’re building a solution that will be used to handle real patient data, you need to extend FHIR to meet your business or organizational requirements.
The best way to do this is to build an Intercept Layer that sits between your consumers and your FHIR server. What sits inside that layer and the extent to which you manipulate and validate data are up to you and to your business.
---
Download my “FHIR Architecture Decisions” book
FHIR Weekly
Join 1,100+ business and technical leaders.