Improving Patient Care with Twilio SMS

Ray Walters
Thirty Madison Engineering
5 min readMar 18, 2021

At Thirty Madison, we help people living with chronic conditions. As part of this, we offer subscriptions to our patients in which we ship products to them on a recurring cadence. This varies based on the product, but an example would be a 30-day supply that they receive every 30 days.

Some of the products require prescriptions from doctors, and these prescriptions are valid for a year. This means that every year, our patients go through a new consultation to renew these prescriptions.

The Old Way

When the patients first sign up, they complete a consult and their answers are reviewed by the doctor, who can follow up with more targeted questions. When the prescription renewal rolls around, the patients come back to our website and answer another, shorter consult. This can be annoying, and there’s a percentage of people who never start the consult, and another percentage who start the consult…then wander off, never to be seen again.

Since treating a chronic condition requires continuous care, this isn’t good for their health, and their health is important to us. They came to us for help with a problem, and stopping their treatment because of an online questionnaire isn’t healthy. So, we wanted a better solution. Something with less friction, a lower barrier of entry. Something that was so easy, it’d be more difficult to not do it.

Something like a text message.

The New Way

Our recent attempt involves sending eligible users a text message with a carefully crafted question, and they can reply with a simple “Yes” or “No”. If they reply “Yes”, we send them over to the doctor who reviews their case and asks any questions. If everything looks good, their prescription gets renewed.

Digging into Details

Only certain people who meet numerous eligibility criteria receive a text message. Every day, an automated job will query for these eligible patients and send each phone number to Twilio Studio, where we have a workflow defined. Twilio Studio starts with sending our carefully crafted message. Then, it waits. If the person responds within two days, it sends the response to a ‘contact’ webhook on our server. Otherwise, after two days, we send their phone number to a ‘no contact’ webhook on our server.

Contact

On our server, we assemble the response with a copy of the question we sent them, and send that to the patient’s doctor for review. Depending on how the patient responds, we analyze the response and annotate the message to the doctor to ease their workflow.

No Contact

Some people don’t like text messages, or for other reasons ignore or forget about the message. If we don’t hear back within two days, we send our carefully crafted question in an email. It isn’t quite as convenient, but any reply will show up for the patient’s doctor to review.

Simple, Right?

This is not a very complex situation, really. Send a text via Twilio, leverage their tools to manage the workflow, and then hand things off to the doctor to get a renewal on the prescription. Of course, there were a few stumbling blocks along the way.

Complex Queries are Expensive

There were a number of criteria to find patients who were eligible to receive a text message. This resulted in a lengthy SQL query. We had tested it quite thoroughly to verify that it included all the people we wanted to receive a text, and excluded everyone who should go through our old renewal process. Then we released our query, and our database latency went from under 200ms to over 4 seconds:

We stopped running the jobs that called that query, and started investigating. While we were very conscientious about testing the users returned by the query, we weren’t so careful about the time the server spent retrieving those users. We dug into it, and discovered a problem with the common table expressions. We had multiple CTEs, and we were actually duplicating work between expressions.

This isn’t the real SQL, but it can serve as an example. We had a CTE with some users we wanted to exclude, and another that had a basic set of users, then some that would further restrict the selection.

However, we created these piecemeal, and ended up selecting from the ‘users’ table each time. The largest savings when refactoring the SQL was to exclude a chunk of users in the first CTE, and then moving forward use the results of that expression instead of the basic ‘users’ table. Once we did that, and consolidated a few similar pieces of duplicated work, we managed to cut the query time by over 90%.

Broken by a Line Break

Twilio Studio is a powerful tool, and overall Twilio has outstanding documentation. We had a problem with the call to the webhook, though, and simply couldn’t find an answer in the docs. It turned out to be caused by a newline character:

Twilio would handle newlines just fine while sending and receiving text messages, but if there was a newline in what we tried to send to our webhook something went awry during transmission. We stripped out newlines, and now everything runs smoothly.

Next Steps

We are still evaluating responses to this new method of continuing care for our patients. However, we’ve had an overall positive reaction to the experience, doubling the response rate compared to our more involved renewal process. And, the more people that continue their care, the healthier they’ll be.

We are hiring! If working on projects like this sounds exciting, please come and join us!

--

--