Healthcare dev teams need to ship features and fixes quickly. HIPAA’s Security Rule requires a detailed audit trail. How do we square this circle? Here, I’ll make the case for turning every promise into code: Terraform modules, CI gates, deployment guardrails, and runnable scripts that emit verifiable proof as the default behavior.
Setting this stuff up retroactively can be a huge pain. But setting it up automation around compliance from the beginning isn’t so bad.
Use ‘Infrastructure as Code’
If you’re building a one-off prototype, you can usually get away with setting up servers and services by hand. The web interfaces for most modern cloud providers are…fine. They do the job. Some of them even come with fancy AI assistants to help translate between what you want (some storage, to rent a computer, a spot for DNS records) and what each service actually calls that thing (S3, EC2, and Route53). It’s feasible to set things up entirely by clicking around on a webpage.
Here’s the thing, though: when you stop working on that project for a month, or when anything stops working, you’re gonna be stuck. And when you’re building something that handles PHI, you have to be able to find everything and defend your choices for at least six years.
That’s only possible with durable documentation. Brains forget, but documents don’t. Unless you’re excited by the notion of having to remember how and where you set up that one Lambda function, five years ago, and how to deploy a new version of it, you’re going to want some really solid documentation and automation. Fortunately, modern infrastructure as code has got you covered.
Automate compliance with IaC.
Once your infrastructure is governed by code, you can start making life easier for yourself using the most common of software dev tools: abstraction!
Say you’re setting up a database. You could set it up from scratch every time, and hope that you remember the right switches to flip to enforce the Security Rule’s encryption requirements properly. Or you could figure it out once, and abstract that knowledge into a module called something like EncryptedDatabase.
Now, not only have you made it safe for yourself to forget those flags, but you’ve also added clarity and intent to the rest of your codebase. When the next developer looks at a service, they won’t have to wonder, “Was this one supposed to be encrypted?” Instead, they’ll see EncryptedDatabase, and know what you meant.
Because it’s just code, you can bring all of your developer intuition to bear on the problem. Use good names and abstraction to make the code readable and understandable, whether it’s application code or ops code.
Automate compliance with CI/CD.
Automatically test all the things.
With your infrastructure captured in code, you can test more, more often, and save yourself from costly accidents. Take PHI audit logs, for example. It’s one thing to say “I’m pretty sure that a bunch of failed login attempts will be obvious in the logs.” It’s another to be able to prove that to your team for every single commit that ships to production.
When your infrastructure is bespoke, an automated test that spins up a clean copy of your application, some storage, some compute, and enough audit logging infrastructure to actually prove the assertion above would be a huge pain. But with modern CI tools, and especially with containerized development, we can make the computers do those checks for us.
This isn’t so different from the automated end-to-end acceptance testing you’re already doing. Just think a little more broadly about the set of stakeholders you’re testing for. It’s no longer just end users. Now you’re also trying to build confidence that your system works well for auditors and other external authorities. They may have more regulatory teeth than a single end user, but the principles are the same. Figure out what they want, encode it in a test, and run that test regularly.
As with complicated end-to-end tests, engineering discipline is important here. It’s easy to build a slow, broken, and fragile test suite that slows the team down. That’s why it’s important to work with a team that understands how to build a great test suite. One that works now, and will continue to work as things change.
You already know how to do this.
Building great digital health software is honestly not all that different from building great software in any other domain, albeit with more stakeholders, and some stricter requirements.
You’ll explore a complex space of requirements, translate them into working code, and then prove to yourself, to your team, and to other stakeholders that the code does the right thing. Use abstraction, automated testing, and engineering rigor to ensure that it stays true even as the code and the requirements change.
Obligatory Pitch
If that all sounds complicated, or boring, and you’d like someone else to figure out the details for you, get in touch! We like building this stuff, and we’re pretty good at it.
This post is part of a series on digital health. Read previous installments here:
Handling HIPAA: A Developer’s First Steps
Prepare for a HIPAA Audit Like It’s a Production Launch