Healthcare RBAC: building access control that holds up
Most apps get away with "admin" and "user." Healthcare software doesn't get that luxury. A physician, an attorney, and a billing admin need three very different views into the same system.
I built the permission system for Synectus Medico around six distinct roles. Here's what actually made it hold up in production, not just in a design doc.
Modeling the actual clinical roles
Six roles is not a magic number, it's what mapped onto the actual people using Medico. Your platform might need five, or eight.
Super Admin
Sees across every clinic on the platform. Creates clinics, manages platform-wide settings, sends broadcast notifications.
Clinic Admin
Runs one clinic. Manages staff accounts, configures settings, has billing and operations visibility for that clinic only.
Executive
A clinic-level leadership view: cross-physician analytics and revenue reporting, without account-management permissions.
Physician
Sees their own patients, their own exam queue, their own report drafts. Not another physician's caseload in the same clinic.
Attorney
Sees only their own clients' cases: billing status, LOP documents, case timeline. Not internal notes, not other attorneys' clients.
Doctor
Referring physicians and sub-clinic doctors. A narrower view, usually limited to patients they've referred.
Route-level and component-level enforcement
Route-level protection
Certain pages are only accessible to certain roles. Route protection checks the user's role from their JWT before rendering anything.
Component-level permission keys
Every interactive element has a permission key. Components lacking a required key are removed from the DOM entirely, not disabled.
A visually disabled button can still be inspected, its handler is still attached. A button that was never rendered doesn't have that problem. It costs almost nothing extra to build it this way from the start.
How I actually arrived at these six roles
I didn't start with six roles on a whiteboard. The process matters as much as the result.
List every job function
Front desk, billing staff, clinic owners, treating physicians, referring physicians, attorneys, paralegals, the platform operator, every distinct function that touches the system.
Group by data access, not job title
Front desk and billing staff ended up sharing a permission set close to Clinic Admin. Paralegals shared the Attorney access pattern rather than getting a separate role.
Design roles around access patterns
Two people with different titles who need identical data access can share a role. Two people with the same title but different access needs probably need separate roles.
If your access control lives only in the frontend, you don't have access control
In Medico, an attorney calling the patient list endpoint gets back only their own clients, because the API pre-filters the query by the attorney's ID pulled from their JWT token. It doesn't matter whether the request came from the app's UI or a hand-crafted API call. The filtering happens at the data layer, not the presentation layer.
Dynamic permission management
Roles shouldn't require a code deploy every time a clinic wants to adjust who can do what. Medico's permission map is data, editable through an admin interface, no engineering ticket, no waiting for a release cycle.
Testing an RBAC system properly
Automated tests assert, for every role, exactly which endpoints return data and which return a filtered response. Manual QA catches the subtle visual leaks automated tests are easy to miss, a tooltip or dropdown showing something it shouldn't.
Frequently asked questions
Good healthcare RBAC matches software permissions to how the organization actually works. Get the modeling right early, retrofitting granular RBAC later is a much harder rebuild.
Talk Through Your Role Model