3 post(s) tagged with "health ecosystem"

View All Tags

I have a secret to tell you.

I have a secret to tell you. It's about the healthcare system and what Commure has been building.

We believe that a big part of the problem with US healthcare today is the lack of innovation in everything outside of medicine itself, and especially the legacy software that runs America's hospitals. Healthcare needs better software at its very core, starting with better software for doctors and eventually for everyone involved. The backbone of innovation in today's world is digital and virtual: the twin forces that have transformed many sectors of our society, not always for the better, but always decisively. Commure has been building a way to harness this power and to do so responsibly, and we are finally ready to talk about it.

alt text

What are we announcing today?

We are really excited to be launching a developer platform and a broad set of APIs and SDKs that developers can use to build modern medical software using open standards. Notably, we built it in close collaboration with health systems to make sure that it both met their security, privacy, safety and regulatory requirements and yet greatly simplified things for developers. This announcement is only a small-yet-important part of Commure's ultimate offering, but it's a crucial step towards delivering on our company's mission of better software for doctors (and nurses and patients).

This is already deployed in production at major US health systems. This is a first for a FHIR-native platform -- meaning one where all of the data is encoded and processed using an open standard (HL7 FHIR) instead of closed and proprietary APIs. It brings modern tech and open API principles to healthcare and enables anyone to use contemporary programming languages and frameworks to build healthcare applications. We also believe we have solved many of the hard problems that any engineer building for this space has to overcome.

For whom did we build this dev portal and platform? The way to build this new software layer is by combining the best parts of Silicon Valley innovation and medical safety expertise, and it's not something that any one company can do on its own: it must be an open, safe, secure ecosystem with hundreds or thousands of specialized teams solving their parts of the problem. That’s part of why we started by working with hospitals and physicians to help make sure the foundation was responsible-by-design.

Once these security and safety controls are in place, innovation in medical software can come from hospital innovation teams, from established vendors, from young inventors, from doctors-who-code, and from innumerable others. What is essential is that all of this growing human and financial investment does not do harm and is not wasted -- that it has a fair chance to make a positive difference on a level playing field.

With that context of why and for whom, I am going to talk a bit more about the technical details of the what. Commure’s stack is a combination of REST APIs on Rust, React.js on TypeScript and containers on Kubernetes. Many software engineers will find most of these either already familiar or on their "list of things to learn in 2020". However, FHIR may be less familiar to those without recent healthcare IT experience.

What is FHIR and why FHIR-native?

The international HL7 standards non-profit created FHIR as an open standard for a comprehensive "healthcare API". Consisting of over 150 different "resources" and numerous operations in a comprehensive JSON REST API, the FHIR standard can be used to express everything in health, from lab results to billing information. Just as important, all of the major technology vendors have pledged support, as have all of the major EHR vendors and the US government. By developing for this open API, applications can be built faster, cheaper and in a way that they interoperate with each other. Unlike past efforts at creating a single API standard for healthcare, FHIR is both technically modern and vendor-independent: there is no lock-in for those using it in their applications. Commure was built with FHIR from the ground up -- what we call "FHIR-native" -- which provides important technical advantages.

Let's now return to the question of why we have chosen to spend more than two years in stealth mode before revealing just a part of what we are building. Many companies have to launch early so they can get their first customers or investors, but Commure already has both. So from Commure's first days, the founders decided to avoid publicity before we had things that were real, before having software someone could touch and use. Healthcare innovation has already had too much hype and false hope -- instead, it requires patience and credibility, and those are easier if one builds before announcing.

I saw no need to write here about the many problems with the US healthcare system: there are whole books written on the subject, from every possible political and professional perspective and I doubt I could say it better. However, it may seem strange to suggest that fixing software is key to improving healthcare, instead of government policy reforms or specific medical breakthroughs. But it's only counterintuitive if one hasn’t spent time digging into it. Every practicing doctor I know complains about their EHR, every patient is frustrated with their patient portal, every hospital CEO is looking for a path to improvement, and everyone is looking for trustworthy information about what works and what doesn't.

So this is what we’ve been building and why. I couldn’t be prouder of the team, and I look forward to developer feedback on this initial public release and there is much more to come. Our long-term goal with this developer platform is to make better software for doctors - and ultimately everyone - by enabling every developer to quickly build and responsibly deploy FHIR-native applications. We believe that better software for healthcare created by everybody will make healthcare better for everybody.

...
Read more
/ 1 min read

Don’t Get BHurned - Keeping an Eye on FHIR Safety.

As a clinician at Commure, one of my roles is stressing the importance of clinically “safe practice” when working with FHIR data. This post will go over some of the expectations clinicians have about their data and demonstrate how ignoring some basic safety principles can lead to delayed or incorrect clinical decisions. For starters, FHIR has a safety checklist which can be found here: FHIR safety, and an accompanying blog post here: FHIR Implementer’s Safety Checklist. I would encourage all healthcare developers to check out Grahame Grieve’s post which includes examples regarding synchronization: Hard #FHIR Safety Problem: Synchronization. Why does this matter? Borrowing a quote from Grieve’s post,

alt text

“These safety checks … are mostly chores, and are easily ignored, but a warning: you ignore them at your peril. Actually, it’s worse than that – you ignore them at other people’s peril.”

The Picky Physician

Physicians consume thousands of discrete data points in their daily practice. To navigate this deluge of data, they have all developed search patterns for navigating this data, whether it be in the EHR, emails, clinical decision support tools, or other sources of data. Search patterns allow physicians to know that by the time they have dissected the chart, they will have consumed all relevant data about a patient to make fully informed clinical decisions. Therefore, even subtle UI changes can be disruptive to these search patterns.

Imagine you are a developer building an app for an inpatient doctor. One common feature request would be a basic metabolic panel that is composed of seven laboratory tests that are commonly grouped together: Sodium, Potassium, Chloride, Bicarbonate, BUN, Creatinine, and Glucose.

Being a helpful developer, you decide to organize these labs alphabetically:

1/2/201/3/201/14/20
Bicarbonate272528
BUN7108
Chloride10098102
Creatinine0.70.60.8
Glucose300200400
Potassium44.34.5
Sodium130128131

Unfortunately, this alphabetizing has a negative effect. Physicians expect this particular set of labs to be in a certain order as a part of their search pattern. Instead, the ordering should look like this:

1/2/201/3/201/14/20
Sodium130128131
Chloride10098102
Bicarbonate272528
Potassium44.34.5
BUN7108
Creatinine0.70.60.8
Glucose300200400

If you had presented the physician with the alphabetical ordering above instead of the expected ordering, they might have looked at the Sodium row expecting it to be the Glucose row and consumed incorrect “normal” valued glucoses (remember they are often skimming through this in milliseconds), whereas the glucose values are rather high here.

I hope the above example illustrates that small changes in UI can have major clinical impacts and the second is that you should constantly iterate with your clinical users to make sure that things are displayed in a way that fits into their search patterns (within reason).

With this in mind, we built the Commure component library to make it easy for developers to create fantastic components for physicians. Take a look at our Laboratory components and Vital Signs components, which takes FHIR Observations and sorts them for you.

When The Absence of Evidence isn’t the Evidence of Absence

Let’s dig a bit further into other assumptions clinicians might be making when looking at your lab table and let’s assume that this data is from Commure Community Clinic. Lets look at the well-formatted table again:

1/2/201/3/201/14/20
CCC- Sodium130128131
CCC- Chloride10098102
CCC- Bicarbonate272528
CCC- Potassium44.34.5
CCC- BUN7108
CCC- Creatinine0.70.60.8
CCC- Glucose300200400

Notice here that instead of just a plain Sodium, Chloride, etc labels, I’m now showing CCC- Sodium. This means that the Sodium is coded as a Commure Community Clinic- specific Sodium code, something that’s very common in most healthcare settings. Let’s say that the clinician is looking at this table on Feb 2, 2020. When they see a table like this, they are assuming that no additional additional basic metabolic panel data is available between Jan 14, 2020 and Feb 2, 2020. When might this be problematic?

1/2/201/3/201/14/20
CCC- Sodium130128131
CCC- Chloride10098102
CCC- Bicarbonate272528
CCC- Potassium44.34.5
CCC- BUN7108
CCC- Creatinine0.70.60.8
1/5/201/10/202/3/20
CCC-Other Labs151123
CCC-Other Labs2411
CCC-Other Labs33232
CCC-Other Labs4212312
CCC-Other Labs51123
CCC-Other Labs623311
CCC-Other Labs7122

Physician stops looking here because everything looks OK on first glance except for the glucose.

2/3/201/10/202/3/20
Mike's Sodium1101123
Mike's Chloride8011
Mike's Bicarbonate15232
Mike's Potassium3.212312
Mike's BUN20123
Mike's Creatinine5311
Mike's Glucose9022

Whoa! That’s some pretty abnormal labs! If you organized your laboratories like this, a physician could completely miss the basic metabolic panel from Feb 1, 2020 because it is not displayed with the other basic metabolic panels and its more than one full screens’ length away from that first set of BMPs. How could this happen?! Well, in this fairly common scenario, the patient had labs from two different sources: Commure Community Clinic and Mike’s Clinic. Because these two sources have their own code sets, the developer here just grouped all the labs by their codes without combining labs with two codes that are actually the same lab type. There are several lessons to take away from this example. First, it highlights the importance of this item on the FHIR safety checklist:

All resources in use are valid against the base specification and the profiles that apply to my system (see note about the correct run-time use of validation) Developers must have clear understanding of the relationship between the data they are displaying (in this case which code systems are being used in the data) and how it interacts with the queries and searches they use to retrieve and display the data.

Second, I will save the details on how to actually fix this problem later, but this example highlights the importance of having good terminology services where maps can be created linking labs like Mike’s Sodium to CCC- Sodium so that they can be grouped together.

Finally, this example also again highlights the importance of having good communication with your physician users. Often, it will be technically slow or impossible to deploy custom mappings to merge data with different codes. In these cases, it is very important to make sure to let your users know that they need to expand their visual search for labs from other sources.

That’s enough of labs for now. Lets take a more detailed look at something Grahme has already touched on in his synchronization example: medications. Again focusing on an inpatient setting, lets imagine that you’re building an app for a physician and he wants you to display all active medications for a patient.

“Easy!”, you say and pull all of the MedicationRequest resources for a patient:

  • Metoprolol Tartrate 25mg PO BID
  • Metoprolol Succinate 50mg PO qday
  • Metoprolol Tartrate 5mg IV q5min
  • Aspirin 81mg PO qday
  • Aspirin 81mg PO qday
  • Aspirin 81mg PO qday
  • Atorvastatin 40mg PO QHS
  • Atorvastatin 40mg PO QHS
  • Aspirin 81mg PO qday
  • Lovenox 40mg SubQ qday
  • Heparin IV gtt
  • Lasix 40mg IV BID

You excitedly show this to the physician, who frowns. “There’s too many medications on here.” In fact, you have forgotten to address this item on the checklist:

For each resource that my system handles, my system handles the full Life cycle (status codes, currency issues, and erroneous entry status)

In the case of MedicationRequests, you need to filter out for only medications with MedicationRequest.status = ‘Active’. Let’s inspect this field.

If you filter out for only the active medications, the list now looks like this:

MedicationStatus
Metoprolol Tartrate 25mg PO BIDActive
Metoprolol Succinate 50mg PO qdayActive
Aspirin 81mg PO qdayActive
Aspirin 81mg PO qdayActive
Atorvastatin 40mg PO QHSActive
Lovenox 40mg SubQ qdayActive
Lasix 40mg IV BIDActive

Oddly, there are still duplicates here. It turns out that you also need to separate inpatient and outpatient medications. For an inpatient physician, you really should only display the inpatient medications. Exploring the Medication. Category codes gives you the following information

MedicationStatusSetting
Metoprolol Tartrate 25mg PO BIDActiveInpatient
Metoprolol Succinate 50mg PO qdayActiveOutpatient
Aspirin 81mg PO qdayActiveOutpatient
Aspirin 81mg PO qdayActiveInpatient
Atorvastatin 40mg PO QHSActiveOutpatient
Lovenox 40mg SubQ qdayActiveInpatient
Lasix 40mg IV BIDActiveInpatient

Great! Now we can just show the inpatient medications:

MedicationStatusSetting
Metoprolol Tartrate 25mg PO BIDActiveInpatient
Aspirin 81mg PO qdayActiveInpatient
Lovenox 40mg SubQ qdayActiveInpatient
Lasix 40mg IV BIDActiveInpatient

Why was it important to only display the inpatient medications? Notice that it’s only on this last cut that the physician obviously notices that Atorvastatin has NOT been ordered in as an inpatient medication. This is a crucial medication for some patients! It would have been very easy to just stop with the “Active” medication filter and display this list to the physician:

  • Metoprolol Tartrate 25mg PO BID
  • Metoprolol Succinate 50mg PO qday
  • Aspirin 81mg PO qday
  • Aspirin 81mg PO qday
  • Atorvastatin 40mg PO QHS (missing on inpatient med list)
  • Lovenox 40mg SubQ qday
  • Lasix 40mg IV BID

However, the physician would have INCORRECTLY assumed that Atorvastatin was already ordered in the inpatient setting.

This example clearly highlights the importance of understanding the lifecycle of a FHIR resource and how it impacts what clinicians expect to see. It also shows how physicians very much a set of contextual filters they expect on their data that they often will not explicitly tell developers. It will be up to the developer to realize that the inpatient context isf important and actually suggests filters on many of the resources that should be displayed. One helpful strategy in this example is to display as much information as possible if you are not sure what is relevant.

As long as you make sure to followup with your physician users about your uncertainty, the two of you together will be able to sort outr the appropriate display filters.

Work fast without breaking things

The purpose of this post is not to scare you away from developing software for physicians. Rather, it is simply meant to highlight of going through the FHIR safety checklist and asking questions when you don’t fully understand how they apply to your software. Commure’s tools will help you iterate quickly so that you can quickly resolve these complex issues with your physician partners. With that all being said, happy coding and don’t get BHurnt.

...
Read more
/ 1 min read

Why Commure uses Rust to make better software for doctors.

One of the pleasures of being a founding CTO is picking your new company’s tech stack. I wanted to write a short blog post about how Commure decided to use Rust for all of our backend code and some of the experience so far. We set out to build better software for doctors, and that means we’re building products that need to be safe, secure, robust and high performance. To me, that suggested we wanted a statically typed and a compiled language for our backend, ruling out such popular choices as Python, Ruby or backend JavaScript. After all, no one wants one’s doctor to encounter a dynamic type error in the middle of their cardiac procedure. That narrowed the choices to: Java, C++, Golang, Erlang and Rust. (It was later suggested that server-side Swift should have also been considered as an option, and I agree - but this was years ago, and it just didn’t occur to me). Let’s go through the options.

alt text

Java is a good option for enterprise software, with a lot of maturity and a big ecosystem of both libraries and developers. Salesforce, my previous employer, is a very successful java shop, but my history with the language started much earlier -- I was part of teams that built some of the first clean room JVMs in the 90’s, and was an early enthusiast for the language. Yet java has gotten a bit long in the tooth, lagging when it comes to language features and its performance hampered by fundamental constraints of the VM’s runtime design. (More on this another time, but I have come to believe that garbage collection is one of them). Similarly, the maturity of the ecosystem brings many potential hires and many potential libraries, but also many unfortunate things. So Java would work, but it was hard to feel excited about it or even that it’s a responsible choice for clinical software that we hope will be used 20 years from now.

C++ is another option. I have a good amount of experience with it, it is mature, compiled, fast, statically typed and - in its modern variants - can be used safely and securely. It has another important advantage of being truly cross-platform and embeddable, so that one could embed one’s libraries or application inside other “master” applications. This is an important consideration for Commure’s product, both in integrating with existing healthcare applications and reducing the effort of mobile development. The two problems are that most experienced C++ developers only use 10% of the language, but they don’t agree on which 10% to use. So if you hire 10 experienced C++ engineers, you’re likely to find yourself mediating a debate about which 10% to use. Add to that the fact that it’s hard to hire C++ engineers and its unpopularity among younger generations, and it’s a hard set of tradeoffs.

The next option is the more modern and popular Go. While new, it certainly isn’t going away, with good adoption across the ecosystem and support from Google. It is compiled, has modern features, has good performance, and has not yet accumulated the plaque in its arteries that plagues other programming languages. The choice to use a garbage collector and a complex threaded runtime gave me pause, however. Those design choices are usually quite benign early on, but my experience with java made me wonder if Go could end up running up against the same barriers as it reached for ever-larger and more complex programs. I also encountered some engineers I respect who had a strong and somewhat hard to understand negative reaction to the language itself. These factors made what should’ve been the obvious option - using Golang - less obvious. Then there is the robust and interesting Erlang. The philosophy of process-based isolation and focus on reliability at scale seemed like a good fit. Its heritage of being born inside a carrier-grade telecom hardware company and the great success that WhatsApp had -- by picking what was an obscure programming language and using it to build a very successful engineering team and a very successful product -- made it worth considering. Yet I did not have any real knowledge of it, and it felt a little bit too exotic for a healthcare software company. I should add that it is entirely possible it would have been a good choice.

Finally, there was Rust. At the time of Commure’s founding, I had been following the language for a few years and used it a bit. There were some important reasons why its design made sense to me: focus on safety and security, compilation to native code, many modern language features, a robust strict type system, automatic memory management with no garbage collector, and the zero cost abstractions philosophy. Just like C++, Rust can be easily embedded inside other programs and runtimes: you can have a Rust library called from a Java or Golang or Objective-C program, but the inverse is far harder.

Rust: A language empowering everyone to build reliable and efficient software.

While the Rust community was very small -- with its creator Mozilla as the main serious user -- it was growing, and the language matched my tastes. It immediately felt like a winner for its time, the same way that Java and Linux felt like winners in their early days. Even years ago, Rust felt like a step forward in the areas where progress is badly needed (like rethinking memory sharing using borrowing & lifetimes) and a stay put in best practices where it’s not (C-like syntax, LLVM compilation, etc). There were some obvious drawbacks, of course. The top one is the risk of adopting any brand new technology at a startup, something that founders are usually told to avoid. The newness of the language meant that there were few Rust engineers available to recruit and not nearly enough mature libraries. It wasn’t at all clear how hard it would be for new people to learn, but it was clear that it wasn’t going to be the easiest language to learn.

So the first step was to start writing our prototype backend in Rust, and have the first engineer try working on it. When he got his first changes committed after a day and without undue trouble, I thought “huh, well, this may actually work out!”, and we decided to keep going with Rust. One memory that stands out from those early days was that I was often writing frontend JavaScript for one half of the day and backend Rust for the other. It was almost a perfect contrast: with JavaScript, it took almost no effort to make a code change but what followed was a lot of time spent browser devtools debugging, with Rust, it often took forever to get past the errors and compile, but once it did, the code almost always behaved exactly as intended, with no debugging needed.

Things have changed a lot since then, both for Commure and for Rust. The experience of using Rust has been very positive -- more on that in future posts, but for example, we have been fortunate to avoid debugging GC misbehaviors in production or chasing elusive undefined behavior. As for building the team, the great thing about making an unusual technology choice early in a company’s history is that people have a clear point of view. It turned out that many engineers were interested in using Rust at work and in the mission of making better software for doctors. Today, Commure has what is probably one of the larger engineering teams using Rust in production and one of the few building enterprise software with it. Meanwhile, the Rust project has grown tremendously in capability and popularity, with many larger companies adopting it for important products. It is now run in even more places, thanks to the rise of WASM in browsers and support from cloud vendors. I’m happy to say that what, several years ago, probably seemed like a very risky choice now appears like a safe option for building healthcare software with its heightened safety, performance and security requirements.

EXPLORE ENGINEERING AT COMMURE
...
Read more
/ 1 min read