Case Studies

What Building a HIPAA-Compliant Platform Actually Takes

8 Sep 2026 Abbas Ali
What Building a HIPAA-Compliant Platform Actually Takes

We spent about three months building a multi-tenant dental referral platform that carries real patient data: encryption, access control, audit trails, tested restores. When we mapped the finished work against every specification in the HIPAA Security Rule, the technical column came out complete and the administrative column had barely been started. Most teams we speak to have the same gap.

Security Rule section Satisfied Partial Not started
§164.312 Technical 12 of 12
§164.310 Physical 5 of 10 2 3
§164.308 Administrative 7 of 24 5 11
§164.316 Documentation 0 of 5 1 4

What we were building

A referral platform for dental practices. A general dentist refers a patient to a specialist, say an endodontist or an oral surgeon, and the referral travels between two independent businesses carrying the patient's name, date of birth, insurance ID, medical alerts, clinical notes and imaging. The two practices then message each other about that patient until treatment closes out.

All of that is protected health information, so the product isn't an app with a compliance layer added on top. The PHI is the domain model: patient records, referral threads, X-rays, DICOM scans, voice notes, and the audit trail describing who looked at any of it.

Practices are tenants. A specialist can belong to several practices and hold different roles in each. A referral can be visible to two organisations at once and to nobody else. That shape is why most of the hard problems in the build turned out to be access-scoping problems in disguise.

By the end we had 60 distinct audited actions, a 15-minute idle session lifetime, six-year immutable log retention, and two restore drills with the results written down.

Technical safeguards (§164.312): the half everyone thinks is the whole job

Twelve of twelve specifications, each one evidenced rather than asserted. Several were proven by watching the system refuse something rather than by reading a config value back: a plaintext request denied, a delete rejected by object lock, a database restored from a point in time twice over.

Getting there had little to do with picking the right libraries. It came down to four decisions that are cheap at the start of a project and expensive to revisit two months in.

An unscoped query is a breach waiting for traffic

The obvious multi-tenant design keeps the practice you're currently working in on the session or the user record, and scopes queries to it. That works until a user belongs to two practices, or a record legitimately belongs to two at once. At that point every query that forgot to scope itself starts returning another practice's patients.

We removed the idea of a current practice altogether. Access is resolved per record, per office, from the caller's own memberships, every time. It means more code and more thought at every call site, and it also means a missing scope shows up as a visible bug in review rather than an invisible one in production. Tenancy is a schema decision. If you get it wrong, you do not patch it in a sprint. You touch every query.

Audit the reads, not just the writes

§164.312(b) requires audit controls, and the instinct is to log mutations: created, updated, deleted. The question a breach investigation actually asks is who saw this patient, and a write log can't answer it. Opening a referral thread is an access event, so is generating a signed URL for an X-ray, and so is a user editing their own phone number.

We ended up with sixty audited actions in an append-only table that is never pruned, mirrored into cloud-provider trails held under object lock for six years. One detail worth copying: when you log a change to personal data, record which fields changed rather than the values. Otherwise the audit table becomes a second, less protected copy of the PHI.

Incident: minimum necessary. Referrals carry a human-readable code so staff can read it out over the phone, and the format embeds the patient's surname. Convenient, but it made the code itself PHI, so no outbound email could contain it. Not in a subject line, not in a notification, not in a "your referral was updated" nudge.

Minimum necessary isn't a policy you write at the end. It constrains identifier design, and that decision comes before the first migration.

The dangerous changes are the ones that look like refactors

About halfway through we changed what one foreign key meant, specifically which practice a referral was routed to. It looked like a reasonable change with a narrow diff. Two files away, a notification service was branching on whether that column was null to work out who was handling the case. Redefining the column inverted that branch, so the people actually working the referral stopped being notified and managers at an unrelated practice started receiving emails with the patient's name in them.

The whole test suite stayed green. Every test covering that scenario built its records with factories, and the factories left the column null, which was a row shape the application could no longer produce. A green suite proves your fixtures agree with your code. It does not prove they still describe production.

A green suite proves your fixtures agree with your code. It says nothing about whether your fixtures still describe reality.

Our first fix was to stop sending the email, and that was the wrong fix. Working out why mattered more than the bug did. The routing column was read directly by the authorisation policy, so the wrongly attributed practice had standing, browsable access to the referral, its message thread, its attachments and its history. Silencing the notification hid the symptom and left the access in place.

Incident: guard ordering. Three checks ran at login: account deactivated, no practice membership, email unverified. The two-factor hand-off sat after all three, because the three of them read like one ordered set of login guards.

They aren't the same kind of check. Two of them refuse a session. The unverified branch grants one and redirects. Because it sat above the hand-off, an account that was enrolled in 2FA but unverified could get a live session from the password alone, and that session could reach the re-enrolment endpoint, which was protected by password re-entry only. Two requests from a compromised password to a second factor paired to someone else's device.

Order a security gate by what each branch does rather than by the list it appears in. Checks that refuse a session can run before a step-up. Anything that grants one has to run after.

PHI leaves through the side doors

Encryption in transit and at rest is the straightforward part. The leaks we spent real time closing were much less interesting than that. Storage keys end in a filename the uploader chose, something like sarah_perio_chart.pdf, so logging a failed file operation pushes a patient's name into an aggregated third-party log sink outside your compliance boundary. A background job with five retries that logs a raw cloud-SDK exception leaks a signed URL five times over. Search indexes hold a plaintext copy of clinical notes by design.

None of these show up on a compliance checklist, and all of them put PHI somewhere you never agreed to put it.

Administrative safeguards (§164.308, §164.316): the half nobody budgets for

Seven of twenty-four administrative specifications, and none of the five covering policies and documentation. The seven we had also clustered together: five of them were the contingency-planning family covering backup, disaster recovery, emergency mode and testing, which happens to be the one an engineer can write without anyone else's input.

Everything that needed a named person, a written policy or an organisational decision was still open. It hadn't been done badly, it had never been started.

Strong encryption with no risk analysis is a worse audit position than modest encryption with one.

A Risk Analysis is a Required implementation specification, and it is the most commonly cited deficiency in OCR enforcement actions. It's also the first document a customer's due-diligence questionnaire asks for. We had encryption, MFA, immutable audit logs and two logged restore drills, and no risk analysis. On paper that is the weaker position.

"Addressable" doesn't mean optional

About half the Security Rule's specifications are marked addressable rather than required, and the usual reading is that you can skip them when they're inconvenient. What it actually means is that you either implement the specification, or you document why it isn't reasonable and appropriate for an organisation your size along with what you do instead. An addressable specification with no recorded decision is a finding rather than a choice.

The Rule scales with an organisation's size and resources, so a two-person software company isn't held to a hospital's standard. It is held to having made a decision and written it down. That distinction is where a lot of small-vendor audits go wrong, and it's better news than it sounds. A defensible row can read "staff use personal laptops, full-disk encryption is required before account activation, we accept the residual risk." Plain language, one sentence.

Termination procedures are where reality is hiding

The specification most often left unimplemented covers what happens when someone leaves. It's also the one that makes for the least comfortable afternoon, because auditing it means going through your own production estate.

Incident: access review. A departed contractor's SSH key was still in the production host's authorized keys file, commented out, and also sitting live in a backup file next to it. A second keypair existed on the host that nobody could account for, and we had to prove it had no trust relationship anywhere before deleting it. Four IP ranges belonging to a deployment platform still had SSH access in the firewall long after that platform was retired. An administrator account with full privileges belonged to someone who hadn't yet completed HIPAA training, so we removed the access and gated it on the training rather than the other way round.

We replaced all of it with an attribution register listing every key, its fingerprint, its owner and why it exists, plus a script that fails if the host and the register disagree. Access control you can't verify on demand is a claim rather than a control.

You're only as compliant as your least-compliant vendor

Every service that touches PHI needs a Business Associate Agreement, and the chain has to be complete end to end, from cloud provider to platform operator to subcontractor. The failure is rarely the obvious vendor. It's the transactional email provider, the error tracker, the log aggregator, or the analytics tag someone added in week three. That is usually a founder's problem disguised as an engineering one: a tool got added because it was useful, and nobody asked whether it could see patient data.

We kept PHI away from the vendors we couldn't cover. Every outbound email is documented to exclude patient identifiers, which is why the referral-code detail earlier mattered as much as it did. We then wrote down which vendors are deliberately outside PHI scope and why, because "we don't send them anything" is only credible if someone recorded the decision.

Some of this isn't yours to write

The last thing we learned was a boundary. As the engineering subcontractor we could draft the risk analysis and pre-fill every technical row from the live system, but we couldn't complete it. Those documents make assertions about a workforce, its devices and its vendors that we have no visibility of, and the first question an auditor asks is who signed them.

So we handed the administrative work over as a structured questionnaire with proposed answers. Most could be closed by writing "approved as proposed", and five needed a name, a date or a decision only the operator could make. Inventing the rest would have produced a document that looked finished and fell apart under the first real question.

Five things we'd say on day one

  1. Budget the administrative half as real work. It's roughly 60% of the Security Rule by specification count, your engineers can't write it on their own, and it's the half a customer's due-diligence questionnaire opens with.
  2. Write the risk analysis early and roughly, in plain language. It's Required, it's the most cited deficiency, and a rough version you keep up to date beats a polished one you commission at the end.
  3. Decide identifiers and tenancy before the first migration. Minimum necessary and access scoping are schema decisions. Retrofitting them means touching every query and every notification path you've written.
  4. Audit access rather than activity. Log who saw what, keep it append-only and immutable, and keep field values out of the audit trail.
  5. Inventory every vendor that could see a byte of it. Either get the BAA, or keep PHI away from them and record that decision. Log sinks and error trackers count.

If you're building something that holds patient data

We've designed, built and operated a HIPAA-compliant platform carrying real PHI end to end: the multi-tenant access model, the audit architecture, the infrastructure under a signed BAA, and the administrative programme that has to sit alongside it. We know which parts are hard, which are cheap if you decide them early, and which can't be bought as a service.

If that's the shape of your next build, or you have something already live and an uneasy feeling about the second column, get in touch.

Start a conversation


Client details are anonymised at our discretion. No identifiers, infrastructure addresses or account references appear here, and every incident is described as the pattern rather than the instance. Coverage figures come from our own mapping of the HIPAA Security Rule at a single point in the engagement, not from an external audit. Nothing here is legal advice, and there's no such thing as HIPAA certification, only compliance you can evidence.

Share

Written by

Abbas Ali
Abbas Ali
Director

Abbas leads Ranium's technical vision and client delivery, working hands-on across system architecture, AI integration, and product development. He has years of experience building custom web and mobile applications using Laravel and PHP, and now brings that same depth to AI-powered solutions using models from Anthropic, OpenAI, and Groq. His work spans industries including healthcare, senior living, and property management.

Abbas organizes Laracon India and has spoken at various conferences and meetups on topics ranging from Laravel development to AI-assisted coding workflows. He believes small, focused teams can build remarkable products when they pair strong engineering fundamentals with the right AI tools.

Related Posts

Fast Site Survey
Case Studies

Fast Site Survey

Empowering Energy Audits with EMPEQ's Fast Site Survey™ Mobile App by Ranium Systems   Executive Summary: Ranium Systems developed the Fast Site Survey™ mobile app for EMPEQ to revolutionize energy audits in commercial and industrial buildings. This innovative application allows professionals to conduct audits more efficiently and accurately, reducing audit time...

16 Jul 2024 Sanjay Thakkar

Want to talk about AI for your business?

Get in Touch Get in Touch