
Christiaan Knaap is CPO at Firely and is the Technical lead responsible for Firely Server. I asked him specific questions about Firely Server and I asked him his thoughts on FHIR in general.
1a. The Firely server is a Windows FHIR server that is managed and hosted by the user. What advantages do you feel an on-prem server offers over a managed cloud server?
First of all, I want to clarify that Firely Server is not just a Windows FHIR Server. It can run on any OS that can host the .NET runtime, including Windows, macOS, Linux, Docker Containers and hence Kubernetes. That allows customers to run it on-prem, or in their own cloud environment as they see fit.
An important advantage is that the option to deploy Firely Server on-premise provides the flexibility of enabling FHIR capabilities without needing to completely re-think classic deployment models. Existing on-premise applications are not forced into a hybrid model. This combines well with another advantage of Firely Server which is the ability to implement it as a facade over an existing database or underlying webservice. This of course is not feasible with a managed server provider.
Next to that, deploying Firely Server on-prem, or in your private cloud environment, has the classic advantage of the customer fully owning the deployment and the PHI therein.
1b. Following on from this, what are the reasons users choose Firely over a managed server provider such as GCP or Azure?
Due to the success of FHIR, we see that more and more health-related applications are being “FHIR-enabled”. Both our payer and health tech customers have large installed bases of their systems. With Firely Server they can enable FHIR capabilities in a way that aligns with that installed base. Either by running it as a sidecar, or by using it as a FHIR facade over their existing systems.
2. Not all FHIR servers implement all features. How does Firely handle these three features of FHIR: Subscriptions, composite search parameters and Patient $everything?
Yes, yes and yes.
Subscriptions are currently implemented according to FHIR STU3 / R4. For the new R5 Subscription framework we are waiting to see how national regulations are incorporating the feature. Meanwhile we also offer more direct ways of integration with PubSub Messaging, allowing you to feed changes to and from messaging systems like RabbitMQ and Kafka.
Composite search parameters are fully supported. And because Firely Server is metadata-driven, you can even define your own.
Patient $everything is fully supported, including settings on which additional resources to include. More info can be found in our technical documentation.
3. Support for FHIR operations varies by server provider. Talk a little about the operations that Firely handles and doesn’t handle. For example, ValueSet $expand and the Patient $match operation. And do users have the ability to add operations not supported?
Terminology operations ($validate-code, $expand, $lookup, $find-matches, $compose, $subsumes, $closure, $translate) are supported, but Firely Server is not as full-fledged a terminology server as for instance Ontoserver is. It can handle FHIR ValueSets and CodeSystems, but with a few limitations. Huge code systems like LOINC and SNOMED-CT are not natively supported. However, Firely Server can transparently connect to an external terminology server to handle those. More info about terminology services can be found on our technical documentation.
Our FHIR .NET SDK is one of the few libraries fully supporting snapshot calculation and – more importantly – FHIR validation. Firely Server brings that power in the hands of the clients with $snapshot and $validate.
Several operations on the meta element are also implemented. And to adhere to our FHIR-nativeness, the $liveness and $readiness health checks are also implemented as FHIR custom operations.
The real power of Firely Server is that any operation can be implemented as a plugin. The plugin framework is completely native to the Server: all our own code is implemented as plugins as well. E.g. the $export operation, required for (g)(10) certification in the US is added as a plugin, and to support Dutch and German national IGs we added plugins implementing the $lastN and $docref operations. Customers have implemented various plugins of their own, either to support a custom operation, or to alter the way the Server handles a request.
4. Performance can be an issue for FHIR servers. Some servers do not fully support certain features because of the performance hit they would entail — examples are _include and _revInclude result truncation. How does Firely handle this and do you see a trade off between speed and the features on offer?
We have chosen to give customers control over the parameters to limit the size of the output. They can configure the default and maximum size of response bundles to control the load on – mainly – the database. This also affects the results of _include and _revInclude. Additionally, they can control the iteration depth for _include:iterate. This way customers can make the tradeoff themselves, according to the use case at hand. A dashboard that refreshes every 5 minutes may need a lot of data, but the request may take a bit longer. An app on the providers’ device should be agile and never make large requests.
5. If you were advising a business looking for a FHIR server provider, what three things would you tell them to ask a potential provider about?
What is the ratio between your development tasks and support issues? This is a nice indicator for the reliability of a server.
FHIR itself and the IG’s built on top of it are updated in rapid succession. What is your track record for staying on top of those changes?
Is the server easily extensible? This will future-proof your investment, even if a feature cannot be implemented right away by the provider.
6. Looking at competing FHIR servers, what do you feel Firely does better than the competition?
I feel that Firely excels at ease of use, while at the same time being very flexible. There are many options for deployment, and more flexibility is available with the plugin and facade framework. Still, we regularly receive positive feedback from our customers about the deployment and documentation. Customers have implemented both plugins and facades without needing support from us.
We use this flexibility ourselves to stay on top of all the latest regulations and certifications. We are in a unique position where we – being one of the initiators of FHIR – have very in-depth expertise of the breadth of FHIR. This assures the customer that we are ahead of the newest developments, can distinguish necessity from hype. The necessary is then added so it works out-of-the-box.
In short, customers can both rely on Firely Server to be and stay certified and have the flexibility to innovate.
7. When it comes to access control, Smart-on-FHIR can be insufficient for real-world applications. Does Firely offer extra features to help with this? Examples might be element level access control or data anonymization.
First of all, Firely Server has full support for SMART on FHIR v2, which allows for more granular access control than v1. On top of that Access Policies can be defined and assigned to each user on behalf of whom a client requests data. The Access Policy functionality is implemented as custom FHIR resources, thus aligning perfectly with the rest of Firely Server. This allows for very precise control over which resources can and cannot be requested.
Specific requirements around redacting the contents of resources can be implemented in a plugin, to meet the needs of the customer precisely and efficiently.
8. A common complaint levied against managed FHIR servers such as Azure is that the server owner does not have access to the underlying database. Can Firely server owners access the database directly and is this an approach you recommend for labor intensive analytical queries?
Customers can indeed access the database directly, whether it is SQL Server, MongoDB or even SQLite. However, to preserve our agility in implementing features and performance improvements, we do not recommend or support this.
Instead, users can tap into the change stream published by our PubSub Messaging plugin and stream the FHIR data into a database optimized for analytics or other requirements.
9. As a FHIR server provider, what were the most difficult parts of FHIR for your team to implement?
FHIR Search is the most complex part to make correct and performant at the same time. FHIR datatypes and search parameter types are combined in a myriad of ways, each with their specific behavior. We are proud that we pulled that off across three diverse types of databases.
Bulk Data Export is another candidate. The functionality itself is straightforward but combined with Smart on FHIR and Access Policies for fine-grained access control – both again based on Search – the implementation quickly becomes more complex.
Runner up will be the feature to evaluate CQL measures. We already host and maintain the open-source .NET library for CQL (with NCQA) and are currently adding CQL evaluation capabilities to the server. Again, fully metadata driven, by CQL measures and libraries. The combination of data requirements and calculations that are part of CQL will make this a difficult task. However, we like to solve these difficulties once for our customers to benefit from.
10. If you were redesigning FHIR today, which features would you leave out or force a re-think on?
Firely was engaged in designing FHIR as it is from the start, Ewout Kramer being one of the three founders. So many of our ideas have been implemented. However, 12 years later new insights surface. I have reached out to him to share his view on your question. This is what he said:
Designing a standard is a constant balancing act between acknowledging you should add a new feature to support a (apparently) common use case, versus the extra complexity you introduce. Although you can make such features optional, they turn into obligation for most server developers since someone will use them at some point. We have added a few features just because we had to support older systems or practices where in retrospect we could have said: you will have to migrate or change your ways, otherwise you cannot use FHIR. You need to be cautious to force changes with a standard, but given the current popularity of FHIR, we could have done so. I also think we’re still adding way too many complex new features using extensions, but that at least is a very democratic process in a way: if they don’t supply value for a bigger audience these extensions will remain niche or fall into disuse.
My personal pet peeves: the way we encode primitives in our json format, the way we declare types in our json format, the introduction of the snapshot in StructureDefinition and the way we use slices to enforce use of extensions in resources. Maybe slicing in general. We took the approach from openEHR and we did get warned by Thomas Beale that the whole snapshotting thing would get complex, but we chose to keep it. Terminology got too complex and finally, the recent addition of a choice of versioning algorithms for our canonicals. That is a clear example of where I’d think we should just have enforced semver.
Final note: we’ve added some links to our technical documentation in the answers. In general, if you’re interested in understanding how Firely Server works, many details can be found there. Feel free to have a look at the complete overview.
---