Health Interoperability
8 Min Read

What’s inside a FHIR Measure

Alexander Zautke - avatar

Subscribe to our newsletter

Subscribe

One of the questions I regularly get when we do work at a customer site goes like this: you build your FHIR server, you get all your data plumbing in place, and then you have a FHIR server. But now what?

Over the last five years, if not longer, we made a lot of progress on establishing a data infrastructure, especially in the US. There are now solid g(10) APIs to get data out of an Electronic Health Record (EHR), Bulk FHIR to handle volume, TEFCA moving records between networks, CMS-0057 requiring payers to enable FHIR APIs.

All the building blocks are coming into place. But now we actually have to make use of that data, because millions of records moving between organizations still leaves you with one question: are we providing good care?

HL7 thankfully already has an answer, and it is a combination of two standards. FHIR Measures define what should be counted and Clinical Quality Language (CQL) defines how to count it. FHIR lets us exchange data, while Measures and CQL are what let us understand it. So the job now is teaching computers, and FHIR servers specifically, how to count.

Are diabetic patients receiving recommended care? Which patients have a gap in care? Which patients are at risk? How are we performing against a quality measure?

All of these start with the same challenge: who belongs in the population we are trying to count?

From a FHIR perspective, a population is a combination of three things. Data, which lives inside your FHIR server. Logic, expressed in CQL, which defines what it means for a patient to be included and which ones we exclude because we do not want to count them. And terminology, which lets you target the correct set of patients, because you need a very clear semantic understanding of a population. What do we mean by “diabetes”, “blood pressure”, or “encounter”?

Every system has to agree on all three. Get that agreement and the goal becomes achievable: same data, same rules, same results. That is why organizations like NCQA (National Committee for Quality Assurance) and CMS (Centers for Medicare & Medicaid Services) are taking this as the new basis for reliable analytics and quality reporting across their programs.

One practical note before you go looking at the specification. There are currently two published versions of the Quality Measure Implementation Guide, and searching for it will probably land you on the old one. HL7 published it under a US realm for about five years, and this year it moved to a universal realm because the rules were never US-specific. Look for the CQM identifier, currently version 2.0.

A Measure resource is divided into four main categories.

Metadata is the cover page: name, canonical URL so the measure is universally identified, version, status, measurement period, and citations linking back to clinical guidelines, so you know which evidence the measure was built on.

Groups are buckets for related populations. If you do diabetes care, you often want to check eye exam results together with kidney assessment and blood sugar control. You do not want to break that into multiple measures, so you combine them into a single set, and each group can have its own rules for calculating results.

Populations are where the counting logic lives. Each one references an identifier pointing to a CQL expression, and each Measure references a single entry point to a Library resource holding the machine-executable code. CQL is thankfully abstract, in the sense that it can be executed anywhere you have a CQL interpretation available, and the open source .NET implementation is one we maintain at Firely.

Stratifiers subdivide a population further, by age for example, so you get more specific analytics. You can have several per population, and they do not have to cover the entire set.

The traditional approach was “give me all the data.” But that’s expensive and difficult to scale. The better question is what data we actually need to evaluate this measure, and that is what effective data requirements answer.

A FHIR server can statically analyze all the CQL expressions inside a library, work out from the terminology which data the measure needs, and reduce the database query accordingly. For a blood pressure calculation, we know exactly which vital signs codes are defined in FHIR, so we expect just a couple of observations rather than every record the patient has.

Most of the time you start with an initial population, the set of all patients you want to analyze. You break that down into a denominator, the specific patients you want to target. For example, everyone who had an ambulatory encounter and could in theory be affected by their blood pressure medication. The numerator is then the specific population you want to analyze against it.

Each population refers to a single CQL statement. The $evaluate operation goes to the database, grabs a FHIR bundle based on the effective data requirements, and gets back a true or false result per subject. Then you just do the counting. It is more or less as simple as that.

There is one exception to watch for here. Some expressions do not return a patient, they return encounters, or procedures, or conditions. A specialized extension, populationBasis, tells you what is actually being counted.

Counts on their own are not the result. The Measure also defines how those counts, or values, get turned into a score. Most of the time you have a proportion measure, the fraction of the numerator divided by the denominator.

Sometimes you have a continuous variable measure, where instead of a fraction you have a measure observation, a value tracked across the population, average length of stay being the usual example. Ratio measures, where numerator and denominator are independent, are really exotic edge cases.

For the last few years everybody was busy getting this technology to work (and to work reliably). But we are now at a point where most engines pass most conformance tests, which means we can start looking at the more interesting use cases.

The clearest one is Gaps in Care, a custom operation in the Data Exchange for Quality Measures (DEQM) Implementation Guide that builds on measure evaluation. With the measurement period set to the current year, if a patient is not in the numerator but should be, somebody gets a notification, a Task resource, or some other clinical action. Pairing that with a Clinical Decision Support (CDS) hook to catch gaps in real time is an obvious next step, though I have not seen many organizations doing it yet.

Measurement periods are just a variable the calculation takes as an input. Yearly submissions are the default for reporting programs, but you can run the same measure across five years without changing anything else.

So, how do we teach FHIR servers to count? Start with your patient population, define your Measure resource, define the CQL statements for each population, do the counting, and hopefully get some good insights out of it. Millions of patients, to Measures, to populations, to counts, to scores, to quality insights.

If you have a server full of data and you are still asking “now what”, this is one of the more concrete answers the standard has to offer, and moving from exchange into quality reporting is the work we do. Firely Server handles measure evaluation, the CQL engine behind it is open source, and we are happy to talk through what your first measure would actually involve.

Alexander Zautke - avatar

By Alexander Zautke

Alexander Zautke is a leading expert in healthcare interoperability and digital health standards in Europe. As Product Manager at Firely, he oversees the development of Firely Server, a platform that enables healthcare organizations to share and manage clinical data using FHIR. His work focuses on making interoperability practical and scalable across diverse health systems and regulatory environments.

Recommendations for you

Explore more topics

Post a comment

Your email address will not be published. Required fields are marked *