The Commure Blog

Thoughts on engineering, healthcare interoperability and FHIR from the Commure product team.

Types

Technology

The easiest way to stay up-to-date. One email every month. No spam, ever.

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

From Professional Chef to Software Engineer: Elise Olivares on Starting Fresh at Commure

Just a few years ago, Elise Olivares never imagined she’d be working in tech. She’d spent her career in kitchens — working as a manager and a freelance chef — and didn’t even own a computer. Then a stint at an online coding school opened the door to a role at Commure. Below, Elise explains what stood out about the company among the 400(!) she applied to, what it’s been like to adjust to a completely new work environment, and how she’s turning challenges into new projects.

alt text

What is Commure, and what’s your role on the team?

Our platform is designed to break down barriers to developing health care software — we want to enable innovations that will help doctors give better, more affordable care to their patients. You can think of Commure as the tech that lets developers quickly build and deploy health-related apps for use in hospitals. The backend is written in Rust, and the frontend, which is basically an access portal for administrators, is written in React and JavaScript. We’re also developing some individual apps that will run on our platform, and I’m working on the first of those right now. It will help doctors with note-taking, and it will also serve as a model to help people understand how Commure works. The note-taking app has mobile and desktop versions, and I’m building the frontend side for desktop.

What were you doing before Commure, and why did you join?

This is my first job as an engineer; I was a chef two years ago. I loved cooking, but I was physically exhausted at the end of every day, and I wasn’t getting where I needed to be financially, especially as a single mom. I’d done some programming in middle school, and I was good at it — I even gave a presentation on object-oriented programming at a Sun Microsystems conference, back when that was a thing — but then I had a negative experience with a teacher that kind of steered me away from the field. I studied neuroscience in college, but I never did anything with it, and I never considered a career in engineering. Then boot camps started to get more popular, and a few years ago I decided to check out Launch School. I took the pre-course on my smartphone, because I hadn’t even owned a computer in years! But I ended up enrolling. After graduation, I think I applied to more than 400 companies. I’d been prepared for the job hunt, and I knew it was a numbers game.

“In any other job I’ve had, I would have hated the idea of still being there in 10 years. Here, it was exciting.”

I found Commure on Hacker News, and I liked that it was small and new. I wanted to be somewhere where I could make a real impact. I also liked the idea of working on something that matters, helping doctors care for their patients. My biggest concern with a company of this size was job security, but Commure is unusual in that we’re in a very good position financially. And then my first phone call with the CTO was immediately the most comfortable conversation of any of the interviews I had, and I could tell on my first visit to the office this was a more mature, serious kind of startup. I love ping-pong and beer as much as the next person, but I was definitely turned off by companies that seemed to see those perks as their major selling points. We have fun, but it was clear right away that people are here to work. So I had a good feeling about it from the start.

Tell us about the transition from being a chef to being an engineer.

I had to slow myself down a bit at first. The first time I got sick, I kept trying to come in and they’d have to send me home. After that, I sat down with our CEO, Diede, and explained that in the world I was coming from, if you’re not running to the bathroom every five minutes, you’d better be at work — and if you don’t show up, you might get fired. Being paid to stay home or take a vacation was new to me. But he told me, “I don’t want you burning out in a year. I want you happy and healthy for the next decade.” In any other job I’ve had, I would have hated the idea of still being there in 10 years. Here, it was exciting. It made me think about how many people we’ll have on the team then, and how much I’ll have learned.

I’ve had to accept that I’m a different kind of engineer. I haven’t been coding since I was 11 like a lot of my colleagues. But I feel like my bosses see my nontraditional background as an asset rather than a liability. Not only can I grow into a better engineer here, but I’m valued for all the other things I bring to the table.

What other challenges do you face at Commure?

Learning can be uncomfortable. That state of “not knowing” is tough for me, and I’m working on how to separate my intellectual frustration from my emotional reaction. It’s been especially challenging because I’ve always learned in more structured environments — and like most young startups, we don’t have a lot of formal mentorship. But Eugene and Diede have been so receptive to feedback about that. I brought a whole list of ideas to our one-on-ones, and they were genuinely interested in finding ways to improve. Diede canceled two calls while we were meeting so we could keep talking, and Eugene kept pulling me aside the rest of that week, because he’d been thinking and had more questions. They really made me feel heard, and we’re already implementing some of my ideas.

“You always see people gathered around whiteboards all over the office having great, spontaneous conversations.

Discussion is definitely encouraged.”

One example is a change to the way we select people for code reviews. I wanted to make sure we don’t end up with a divide between more- and less-experienced members of our team as we grow. So I suggested I set up a script that allows us to select reviewers, like we do now, but also randomly assigns one team member to each review. I think it will encourage people to read parts of the code they might not be familiar with, and to get more comfortable offering feedback. It will also be an opportunity for me to get more experience with Rust. I’ve learned a little, but frontend work has been my focus so far, and I think it’s time for me to branch out.

What’s the process for choosing new projects to work on?

We’re developing processes as we go, but we try not to have too many. We want to focus on what we actually need, not just enforce process arbitrarily. Our sprint board keeps track of what everyone is working on for the week, but there’s a lot of research and experimentation built in. Some tickets are small and easy to solve. Others, like “explore new database options,” could take weeks.

I got to experiment recently with a new language, Reason ML, when we started working on the note-taking app. It’s based on OCaml, but it’s compatible with React, so it can tie into what we already have. I took a few days to do research and learn enough to write a few hundred lines of code, a basic skeleton of the app. Then I presented it to the team. We talked through the pros and cons and decided to stick with React for now, but we may use Reason ML in the future, and it was a fun experiment. That’s very much the culture here. You always see people gathered around whiteboards all over the office having great, spontaneous conversations. Discussion is definitely encouraged.


Interested in working with Elise and the rest of the Commure team? Check out open roles or email Elise to learn more.

...
Read more
/ 1 min read

Software Engineer Pascal Brandt on How Commure is Hacking Health Care

As the first employee of a global health NGO working in Africa and Asia, Pascal Brandt learned directly how tech innovation can be a game-changer for doctors and their patients. Now, he and his teammates at Commure are giving other developers a platform to create groundbreaking tools and help transform health care. Below, he explains why he joined Commure, what sets the company apart from other startups in the space, and what he values in new team members.

alt text

What does Commure do?

We’re building a platform to help developers more easily create health care apps. We do this by offering a nice API layer to work within and handling all the legacy integrations. Right now, doctors spend a lot of time fighting technology instead of helping patients, in part because most hospital records systems are built to accommodate billing departments rather than health care providers. Developers who want to help fix that are often blocked because the data they need is siloed in individual hospitals. Our team speaks both languages — health care and tech — so we can help engineers and entrepreneurs build better tools, which will ultimately make health care work better for everyone.

What were you doing before Commure?

I spent a couple of years as an engineer building backend systems for a big financial company in South Africa, where I’m from. After that experience, I knew I was not going to be happy unless I worked on a problem I felt was important. So I took a job as the first employee of an NGO that did donor-funded global health projects. We built and installed open-source tools for hospitals and clinics all over sub-Saharan Africa and part of Asia. It was really rewarding work, and it taught me a lot about how doctors think and what they need.

“Our team speaks both languages — health care and tech — so we can help engineers and entrepreneurs build better tools.”

Eventually, I decided to come to the U.S. to study Biomedical and Health Informatics, which is like a crossover between computer science and medicine. While I was waiting to start my Ph.D. program, I participated in Stripe’s open-source retreat, which basically pays engineers to work on projects that Stripe thinks are important. I developed an open-source system for electronic health records. Then John Collison, one of Stripe’s founders, put me in touch with Diede, who was about to leave their team to start Commure.

Why did you want to join the team?

I’d been in health care for 10 years at that point, and I’d seen doctors getting burned out and depressed. They got into medicine because they loved to care for patients, but they were spending hours in front of computers dealing with various compliance requirements. It was kind of a nightmare. I knew Commure could have a positive impact. I wanted to work on something meaningful while I got my Ph.D., something closer to my experience at the NGO, versus working on some new social media app that encourages people to spend more time on their phones.

I could also tell Diede not only understood the problem well, but had surrounded himself with co-founders and advisors and a team who understood it, too. These were people who had been in the health care industry and cared deeply about the problem Commure was solving. We have two doctors on the team, for example. They help us understand providers’ workflows so we can build the tools to match. We also have hospital and health care partners advising us who will be the first to use Commure. That they believe what we’re doing is worthwhile was a big part of the reason I decided to join. They understood the space and said, “Oh, what you’re building is exactly what we need.”

What sets Commure apart from other companies in this space?

A lot of startups pivot and completely change their plan, but we’ve stayed pretty focused on the same product scope and deliverables over time. Our initial vision has been validated, and I think that’s a really good sign. We also have a longer-term strategy than most companies. Selling an app to a hospital can take years, and we knew that up front. We’re well-funded, and we’re looking at least 10 years out. We don’t have to worry about achieving crazy growth, because it’s not part of our strategy.

I think our other big strength is the diversity and commitment of the people on our team. We have doctors and CS grads, but we also have people from boot camps who used to be chefs and accountants. That variety of perspectives is valuable. And everyone here is empathetic and extremely dedicated. We’re all driven to improve the lives of patients and the people who care for them.

Tell us about the challenges you’re facing.

There’s a pace differential that can be frustrating between a startup environment like ours and an established health care system. Hospital CIOs and CMIOs are often conservative about change, whereas we want to move more quickly. But for Diede, that’s a fun challenge. He enjoys convincing people that there’s a better way.

“We’re well-funded, and we’re looking at least 10 years out. We don’t have to worry about achieving crazy growth, because it’s not part of our strategy.”

What’s fun for me is the nitty-gritty technical problems we get to solve. There are lots of interesting deployment and DevOps challenges, because we’re balancing the need to make data access simple for developers with the need to make the platform ultra-secure. For example, you have to be able to record and audit every event, like when someone logs in or updates a patient’s record. But at the same time, you can’t store protected health information on public servers. Plus, health care privacy regulations like HIPAA are notoriously vague and inconsistent. So we implement solutions that go far beyond their minimum requirements, to make sure patients’ information is safe.

Data exchange is another interesting engineering problem, because we’re integrating all these non-standardized legacy APIs. It’s way more complicated than simple data-mapping, because medicine itself is super complicated. You have tens of thousands of codes that hospitals use to charge insurers, and different health systems often interpret the same codes in different ways. That makes mapping between hospitals really difficult, but figuring it out is how we’ll make it possible for engineers to build new apps.

What do you look for in new hires?

Everyone who joins should be willing to at least be exposed to every part of the system. That may change as we scale, but right now I think it’s important for our engineers to have the entire context before they start working on a specific piece. That said, people do gravitate toward individual areas of interest, and we do have clearly defined buckets of work. There’s a lot of UI and UX to be done, for example. Or a systems engineer can focus on our core API server, which we’re writing in Rust. Rust is a relatively new language and comes with quite a learning curve. But it’s increasingly popular and pretty sweet, so we decided it was worth the investment.

We also want people who can collaborate with a variety of stakeholders in health care and in tech. You have to be able to talk with a doctor, an IT person, and someone in billing, and then synthesize that information to help build something that will work for the entire hospital system. You have to empathize with the developers who will build on top of our platform, and understand the frustration they feel in the current environment when they can’t get answers to basic questions. Our job is to understand both worlds and be the bridge between them.


Interested in working with Pascal and the rest of the Commure team? Check out open roles or email Pascal to learn more.

...
Read more
/ 1 min read

Software Engineer Esteban Küber on the Challenges and Opportunities of Rust and Commure

Many software engineers pick up new programming languages when they start a new job. But for Esteban Küber, learning Rust first is what led him to Commure. Below, he explains why he decided to join the company, weighs the pros and cons of writing the platform in a relatively young language, and shares details on the team’s upcoming projects.

alt text

What problem does Commure solve?

Like most legacy industries, health care is bogged down by entrenched processes. There’s a gap between what companies see as state-of-the-art and the actual state of the art, and there are a lot of regulatory requirements. That adds up to an extremely high barrier to entry for someone who wants to innovate in this space. Commure takes care of all the data integration and offers a simple, elegant API, which allows developers to focus on what they want to build.

But we’re also solving a problem on the provider side, where we facilitate access to their data. The people who typically purchase health care software aren’t the ones who actually use it, which means it’s optimized for reporting rather than to help doctors care for their patients. Doctors often have to enter the same information multiple times into multiple systems, for example, which is a waste of time and increases the risk of errors. Part of what we’re doing is minimizing that clerical work and making it easier for doctors to do their jobs.

What were you doing before Commure, and why did you decide to join the team?

Prior to Commure, I was at Twitter for five years, working on the infrastructure side. I built tools for other developers to use, including administrative tools for a key-value distributed database called Manhattan, and I generally tried to keep people from getting paged at 2 a.m. Before that I spent several years as a contractor for Google in Buenos Aires. I found Commure through the Rust community, which I got involved with a couple of years ago. I’d been hearing about Rust for a while, and when 1.0 came out in 2015, I decided it was as good a time as any to learn. It was painful at first — I didn’t get anywhere. But I picked it up again a few months later, and that time I started contributing right away.

“We’re building something from scratch, which is exciting, but we also know exactly how it’s going to help our customers.”

When Diede and Eugene told me about the platform they were building, my first reaction was, “You guys are insane.” I knew health care had a lot of entrenched players, and the problem they wanted to solve seemed insurmountable. But as they explained more, I realized they weren’t just picking a random industry to try to disrupt, like a lot of startups do. The people on this team have real experience in health care, and so do the advisers. They were making very informed decisions about how to approach the product. I was also interested in moving to a startup after spending so much time at larger companies. In a big organization, it’s easy to get in the habit of seeing issues as someone else’s problem, and I liked the idea of being on a team where everyone is passionate about finding solutions. What set Commure apart from other small companies, though, was the clear vision and objective. We’re building something from scratch, which is exciting, but we also know exactly how it’s going to help our customers. It’s very different from most startups in the Valley.

Tell us more about why Commure uses Rust.

The founders made a bet on Rust, but it was an informed, strategic bet. The risks are obvious — it’s a very young language, so it doesn’t have the same breadth or depth of resources as Java or Python or Ruby. Rust does have good bindings to C, so you can get some existing libraries that way, but the lack of existing resources is still a potential downside. And while the compiler itself is very solid, the surrounding tooling is less polished than what you might be used to with something like Visual Studio or Xcode.

But there are elements of Rust that really appealed to us. It basically applies 30 years of industry best practices and collective wisdom to a very low-level programming language. You’re writing code that could be at home in a very high-level language like Scala, but without any of the performance issues created by interpreting that language on a virtual machine. There’s also an emphasis on speed and ergonomics — and on accuracy, which will help us sleep at night when our platform is running in hospitals.

The other big benefit is the Rust community, which is really welcoming and open. It’s easy to get help with even the most difficult problems, and people are very passionate, which shows in the technologies they’re developing. Some of the software we write at Commure is eventually going to be open-sourced, because we’ve gained so much from this community and we want to be able to give back.

Can you share a recent project you’ve enjoyed?

In my first couple of months, I’ve spent the most time on the authorization layer, which is obviously critical for a health care platform. There are specific legal requirements around what we do for authentication and login. One of my projects in that space was implementing a new library to parse and evaluate XACML policies. XACML has been battle-tested in multiple industries, but it’s not common in startups because it relies on XML. It’s more of an enterprise technology, almost like a very small programming language. It was fun to work on, and I’m pretty happy with the results — we’re passing 430 of the 450 conformance tests, including all of the ones that are relevant for us. I think it’s going to be important for Commure going forward.

What kinds of challenges can a new Commure team member expect?

Because I hadn’t worked in health care before, one challenge for me was getting acquainted with the FHIR, or Fast Healthcare Interoperability Resources, protocol. I spent quite a bit of time reading up, to make sure I had the context I needed to understand its technical decisions and features, so I could properly implement it.

For someone new to Rust, I think it would also be difficult to lose the baggage of your experience with higher-level languages. There are patterns you can apply in Python or Java that flat-out won’t work in Rust. What’s really happening is that Rust is revealing cases where that pattern won’t work; it was just silent before. Still, that can be frustrating at first.

“We have a high-level roadmap, and we know which four or five things need to happen in the next month or two. From there, it’s just a matter of who’s most interested in what.”

As far as the specific projects you can work on here, we’re at the stage right now where we have the basic building blocks in place, and there’s a lot of variety in terms of what we do next and where you can focus. We have frontend work to do, performance-intensive code and libraries to write, and metrics to get in place to make sure our platform is easy to monitor and maintains a high level of uptime. We want it to be robust, from how we handle changing configuration files in a running service to how we deal with our storage layer. We do think it’s important for team members to get to know all the different parts of the platform, but there’s a lot of flexibility in terms of individual projects. We have a high-level roadmap, and we know which four or five things need to happen in the next month or two. From there, it’s just a matter of who’s most interested in what.


Interested in working with Esteban and the rest of the Commure team? Check out open roles or email Esteban to learn more.

...
Read more
/ 1 min read

Profiles in FHIR

A follow up from a recent internal discussion about merits of Rust static typing for FHIR data.

In this post I'm going to take a look at the profiling in FHIR(r). I'll open with a statement which sets up the major constraint for FHIR applications:

FHIR is not a standard per se, but rather a "platform specification"!

What that means is that FHIR specifies only features which are common across jurisdictions and healthcare ecosystem in general. FHIR is by design incomplete.

The true interoperability of FHIR is defined via feature called "profiling". It's the way FHIR specification could be extended for specific scenarios, use cases, jurisdictions, and so on.

So far, many FHIR API implementations and users are successfully ignoring profiles (most of the time), however, my expectation is that everyone will have to deal with profiles 100% of the time, even though they could only define 20% remaining percent of the behavior!

Given that, in my opinion, it is impossible to talk about statically typing the data unless there is at least a basic understanding of profiles.

Profiles

What is a profile? Basically, it's another "StructureDefinition" which "constrains" the base definition it attaches to. Sounds deceptively simple, but they in fact are way more powerful than they look!

The easiest thing a profile can do is straightforward restriction on a base element. For example, "Patient.name" element is optional ("min" cardinality is 0). Profile can make field required by setting "min" to 1. For example, let's look at US Core (it's also called an "Argonaut Project") profile for "Immunization". For the "Immunization.date" field the "min" cardinality is set to 1 -- making it a required field.

An application developed with such profile in mind might expect that "date" field on "Immunization" matching US Core profile is a non-optional date value2.

Bindings

Another common use-case for profiles is to constrain bindings on elements. There are many possible scenarios here, but the general idea is that profile can restrict which codes could be used, but not allow for new codes (codes which are invalid in the base structure or profile cannot be made valid).

Again, this is somewhat deceiving. If base binding is "example", profile can, for example, replace it with "required" binding. Technically, this restricts possible codes, but from the application point of view it can be viewed as "replacing" binding with a different one.

An example of such profile is US Core Patient, which changes binding for the "Patient.communication.language" element to "http://hl7.org/fhir/us/core/ValueSet/simple-language".

An application developed with such profile in mind might expect the binding defined in profile, not the binding defined in the core specification. Although, the binding stays extensible -- so any value from the base definition could still be used!

Extensions

Before looking at more complex cases, let me introduce another piece of the puzzle, an "Extension".

"Extension" is a complex type which is crucial to the whole FHIR extensibility story. By itself it is just a pair of URL and some value (which could be of any type). However, the idea is that you can put any kind of data in it -- annotated with URL which would define its semantics.

Every data type extends complex type "Element", which has an "extension" field with value of list of "Extension"s. Therefore, it allows to add custom data to every possible place of FHIR resource -- even inside primitives (although representation of these in JSON is a bit crazy)!

Profiling Extensions

So, another possible use of profiles is defining profile for "Extension" element. This allows to restrict an "Extension" in a way that it becomes your custom data type (remember, FHIR does not allow you to define your own types and resources outside of this extension/profiling mechanism!).

For example, let's take a look at the "birthTime" extension (the easiest is to look at its definition inside "differential" field -- this would be the difference with base definition).

It specifies that "url" field can only have one possible value, "http://hl7.org/fhir/StructureDefinition/patient-birthTime". Also, it specifies that this extension cannot have its own extensions ("max" cardinality of "Extension.extension" is "0"). Finally, it specifies that value type can only be "dateTime"1.

Now we have a way to allow custom data (typed) on an existing field (the "birthTime" extension specifies context "Patient.birthDate", which means it can only be used on "birthDate" field of "Patient").

The only guarantee provided is that if application would see an extension with this URL, it should comply to this profile. Nothing is known upfront about if this extension exists at all (Patient definition doesn't say anything about it)!

Slicing

What if we want to attach our extension to the Patient resource? Let's say, we want to define an "ethnicity" field on our resource for our US Core Patient profile on Patient.

Please, meet the slicing! It's a technique to specify some constraint on a list of elements. There are two common use cases.

One use case is to specify additional requirements on a subsets of values of the repeatable element. For example, in CareConnect Patient, a "Patient.name" element is sliced by the "use" field. Then, for an element with "use" set to "official", the cardinality is set to "1" (both "min" and "max") -- which enforces that Patient has exactly one official name!

This could be seen as creating essentially a new field on a Patient, "officialName" (or, rather, a selector which will return one of the elements from the "Patient.name" array). If application is developed with this profile in mind, it might expect this field to be defined on the Patient resource!

Another common use-case for slicing (I think, it's actually the most common one) is to slice off an extensions list. The typical definition would be something like "slice me "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity" extension off the extensions on Patient resource and set its cardinality to 0..1". This would essentially add a new field to the Patient, with data type defined by the extension profile!

Again, an application assuming Argonaut profile (US Core Profiles), will expect Patient to have a field called "ethnicity" on the "Patient" resource itself!

Slices: Complex Types

As a side note, profiling extensions can also create "custom" complex types! The convention is that the extension itself will be a "complex type", with no value of itself ("max" cardinality restricted to "0").

Then, the "extension" field on the extension itself could be profiled in a way that each "slice" is given a fixed URI and restriction on value data type. The fixed URI of these "fields" is usually a simple identifier, like "individual" for the "acceptance" extension.

This essentially defines a new data type, with fields of given types!

Two Uses of Profiles

There are two common uses of profiles in the context of the system: resource profiles and system profiles. Resource profiles are ones which are guaranteed for every resource in the system. For example, US Core Patient profile used in such manner would guarantee that every Patient resource returned by an endpoint is a valid US Core Patient resource.

The system profiles, though, only guarantees that these profiles are used in the system, but they are used on a per-instance level.

An example of such profile would be set of profiles on top of "Observation" resource, for example, "Blood Pressure" profile3. Not every observation is a blood pressure observation, but those which are, should comply to the blood pressure definition (for example, should have LOINC code of "85354-9").

This essentially defines a new type which application dealing with blood pressure might expect.

It is crucial not just for interoperability but also for safety. Note that the difference between guarantees given by a base "Observation" resource and "Blood Profile" is huge: base definition is essentially a collection of "anything we observed for whoever", whereas blood pressure observation is very specific.

What Next?

The key take away should be that profiles are important, they could do a lot and they define the real guarantees. Also, they are highly dynamic across multiple dimensions (could be defined "at runtime", could apply on a per-instance basis, could modify resource significantly, and so on).

I was planning to present an idea how we can map these profiles to Rust traits, but this post is getting a bit long, so see y'all next time!

References


  1. The tricky part is that an extension is considered a valid value for primitive, which means application might still receive an empty date field! Oh, well...
  2. There is some tricky part here -- this restriction is set on "expanded" variant of the field, "valueDateTime" rather than its base definition "value[x]"
  3. It's in fact defined on top of "Vital Signs" profile, which is defined on top of "Observation" resource.
...
Read more
/ 1 min read