
Multi-Tenant Architecture for Telehealth SaaS — PHI Stays Per-Tenant
Postgres RLS as the PHI boundary, audit logs that survive 164.312(b) review, BAA scope that does not sprawl — architected so cross-tenant PHI exposure is structurally impossible, not just unlikely.
The problem
A telehealth SaaS hits the multi-tenancy wall earlier and harder than most other verticals because the cost of getting it wrong is not contained by the engineering budget. A standard B2B SaaS that leaks one tenant's data to another loses customers and trust. A telehealth SaaS that leaks one clinic's data to another triggers a breach notification under 45 CFR 164.408, an OCR investigation, mandatory written notice to every affected patient, and depending on the size, a HHS Wall of Shame entry and a wave of state attorney-general inquiries. The "we found out from a support ticket" failure mode is not survivable in this regulatory regime.
Misaligned tenancy boundaries
The architectural problem underneath that risk is that telehealth applications carry several different tenancy boundaries at once and they do not all align. Clinics are tenants for billing and BAA purposes. Providers are users with roles inside a clinic. Patients are records, but patient-portal users are also identities. Multi-state clinic groups add a residency dimension where data for patients in some states cannot legally cohabit with data for patients in others. State-by-state telehealth licensure rules mean a single provider record might have different scopes in different patient contexts. The application code that has to enforce all of this correctly tends to start out as a few WHERE clauses, and six months in it becomes the highest-risk surface in the codebase — touched by every new feature, audited by every new compliance review, broken by every refactor that did not know to check.
PHI that does not sit still
The deeper problem is that PHI does not sit still. It moves into webhook payloads when something connects to billing. It moves into background jobs when something processes audio for transcription. It moves into the logging pipeline if the logger captures query parameters by default. Each movement is a potential cross-tenant boundary crossing, and each potential crossing is a breach risk that lives outside the database where the original RLS policies live. A multi-tenant telehealth architecture has to think about PHI as a typed object that knows which tenant owns it, not as rows in a table that happen to have a tenant_id column.

What changes for your business
Postgres as the PHI boundary
The correct architecture pushes the PHI boundary down into Postgres itself and treats every layer above it as a defense-in-depth check, not the primary control. The PHI tables — patients, encounters, notes, attachments, messages, claims — all have Row Level Security enabled with FORCE ROW LEVEL SECURITY set on each, so migration scripts and admin tools that run as the table owner cannot silently bypass the policy. Policies read the tenant_id (clinic_id) directly from an immutable JWT claim, not from application-supplied parameters. The default-deny behavior documented by Postgres means that a newly added PHI table without a policy returns zero rows to every query — the wrong failure direction is impossible.
Persistent clinician identity across memberships
Above the database, identity is centralized. Each clinician has one user_id that persists across clinic memberships, which is what 164.312(a)'s unique user identification requirement is asking for at the human level. Memberships are the join between users and tenants and carry the role that determines scope within a clinic. When a clinician changes clinics, the old membership is terminated rather than deleted so the audit trail stays intact. JWTs are short-lived; refresh tokens rotate on use; revocation propagates within the refresh window. The auth provider is inside the BAA boundary because the access token, however briefly, carries identifiers that resolve to PHI.
Append-only audit layer against 164.312(b)
The audit layer is the part most teams under-build. 164.312(b) requires mechanisms that record and examine activity in systems containing ePHI, and the practical interpretation is an append-only audit table that captures tenant_id, actor user_id, target record reference, action type, and timestamp for every PHI read and write. The table is partitioned by month and shipped to immutable storage for the retention horizon — commonly six years, sometimes longer depending on state law. The audit pipeline lives inside the BAA boundary because the records reference PHI. Audit log review is a scheduled job, not a manual one, because the regulation requires examination as well as recording.
BAA boundary enforced by tokens, not paperwork
The BAA boundary is treated as architecture, not paperwork. Every system that touches PHI is on a named list — the database, the auth provider, the storage bucket holding clinical attachments, the EHR integration layer, the audit pipeline. Every system not on that list receives opaque internal tokens instead of PHI, so the analytics tool, the error tracker, the marketing automation, and the support desk are structurally incapable of becoming sources of PHI leakage. When a vendor outside the list needs context, it gets a token it can pass back to a BAA-covered system that does the resolution server-side.
What this changes for the business: PHI stays where it belongs without a quarterly audit-prep sprint, because the controls the auditor wants to see are the same controls the application uses every day. Adding a new feature stops requiring a tenant-boundary review because the boundary is enforced one layer below the feature. Onboarding a new engineer stops requiring a week of "here is how our PHI flow works" because the flow is structurally constrained. And the breach notification you do not want to send becomes a class of incident the architecture prevents rather than merely deters.

What gets shipped for telehealth-specific multi-tenancy
The deliverable is a working tenancy layer in your repository, scoped to the telehealth concerns that distinguish this engagement from generic multi-tenant SaaS.
The schema lands first: a tenants table representing clinics (with a region column that drives data residency placement), a memberships table joining users to tenants with roles, and tenant_id (clinic_id) on every PHI table with foreign keys and indexes set up so RLS policies push down into index scans. RLS is enabled and FORCED on every PHI table, with policies that read the tenant scope from the immutable JWT claim. A CI check fails the build if a new migration adds a PHI table without enabling and forcing RLS.
The audit layer ships next: an append-only audit table partitioned by month, a database trigger or application middleware that writes an audit row for every PHI read and write, a shipper that streams the audit partitions to immutable storage on the retention horizon your BAA chain requires, and a scheduled review job that surfaces anomalies (cross-tenant attempts, unusual access patterns, service-account queries that should not have happened) to a queue a compliance reviewer can work.
The BAA boundary ships as documentation backed by enforcement: a named list of every system inside the boundary, a token-issuing layer that produces opaque internal IDs for systems outside the boundary, and integration audits that fail if a PHI field shows up in a payload destined for a non-BAA-covered system. Region routing ships if the customer has multi-state clinics: a router that reads tenant region from the tenants table and directs data operations to the database instance for that region, with cross-region queries forbidden at the policy layer.
```sql -- PHI tables get RLS enabled AND forced so admin scripts cannot bypass alter table public.patients enable row level security; alter table public.patients force row level security; alter table public.encounters enable row level security; alter table public.encounters force row level security;
The engagement leaves your team able to extend the architecture without calling an outside engineer back — adding a new PHI table is a migration plus a policy plus an audit trigger, not an architectural decision. Adding a new clinic is a row insert. Adding a new state with a different residency rule is a region row plus an instance.
What buyers ask first
The questions that come up in the first conversation with a telehealth CTO cluster around: "How do we audit-proof this without a separate compliance project?", "Can we use Supabase or do we have to roll our own?", "What happens to our existing PHI when we migrate?", and "Does this make our BAA list shorter or longer?" The short answers: the audit controls are the same controls the application uses daily, which is what makes the audit cheap; Supabase has a HIPAA-eligible tier and the RLS-first model maps onto this architecture well; PHI migrations run with the same isolation and audit discipline as the steady state, with a checkpoint and rollback path; and the BAA list gets shorter because token issuance moves systems out of the boundary. The FAQ covers the longer versions.
Common failure modes
The patterns that take down telehealth multi-tenancy are recognizable on sight once you have seen them. RLS enabled but not forced is the most common — a policy that passes manual testing under a normal account silently does nothing during a migration script that runs as the table owner. Cross-tenant background jobs are the second — a worker that runs as a service role with BYPASSRLS to do its job, and then a developer reuses that service role for a user-facing endpoint and the tenant boundary is gone. PHI in logs is the third — a debug log statement that captures a query result containing a patient name, shipped to a logging provider that is not on the BAA list. Audit table writes that happen outside the read transaction are the fourth — a separate audit-write call that can fail or be skipped, breaking the regulatory requirement that the read and the audit are atomic. The architecture is built to make each of these structurally hard rather than relying on review.
How BoostFrame approaches this
BoostFrame Engineering AI (BFEAI) runs the underlying multi-tenant architecture — RLS-enforced tenant isolation, centralized identity with refresh-token rotation, per-tenant entitlement via webhook — across seven production applications. BFEAI is not a telehealth product, and we do not present it as one. What transfers is the structural pattern: the FORCE ROW LEVEL SECURITY discipline, the immutable-claim-based tenant scoping, the CI check that no tenant table ships without a policy, and the audit-log pattern that runs inside the same transaction as the side effect. The telehealth-specific work — the audit retention horizon, the BAA boundary mapping, the multi-state residency routing, the PHI-in-payloads discipline — is what we architect against your existing compliance regime and your specific EHR integration, scoped to a three-to-five-week engagement for a seed or Series A telehealth SaaS. The deliverable is working code in your repository plus an audit script your team runs before every release, sized so the second and third apps in your suite can ship on the same tenancy layer without calling an outside engineer back in. The author is Bill Fackelman, co-founder and CTO of BoostFrame Enterprise AI.
Outcomes you should expect
What this delivers
- PHI stays where it belongs without a quarterly audit-prep sprint — the tenant boundary is enforced in Postgres, so cross-clinic reads cannot happen even when application code is wrong.
- Audit logs that satisfy 164.312(b) without bolting on a separate logging service — per-tenant activity, identifiable actor, immutable storage, retained for the period your BAA chain requires.
- BAA scope stops sprawling — the infrastructure surface area that touches PHI is small, named, and auditable, instead of every vendor in the stack.
- Multi-state clinics ship without rewriting the data layer when a new state's residency rule lands — tenant placement is configuration, not schema migration.
Industry data
By the numbers
45 CFR 164.312(b) requires covered entities to implement hardware, software, and/or procedural mechanisms that record and examine activity in information systems that contain or use electronic protected health information — making per-tenant audit logging a Security Rule obligation, not a nice-to-have.
45 CFR 164.312(a) requires unique user identification — assigning a unique name and/or number for identifying and tracking user identity — which means a multi-tenant telehealth app cannot rely on shared service accounts when a clinician's actions need to be traced back to them inside their tenant scope.
Postgres Row Level Security uses a default-deny policy — if no policy exists for a table with RLS enabled, no rows are visible or modifiable — which is the safe failure mode for a telehealth schema where the cost of a wrong-tenant read is a HIPAA breach notification.
Postgres table owners normally bypass row security unless ALTER TABLE ... FORCE ROW LEVEL SECURITY is set, which means a telehealth migration script running as the table owner can silently read across clinics if FORCE is not enabled on every PHI-bearing table.
Supabase's RLS documentation states that once RLS is enabled with a publishable key, no data is accessible via the API until policies are written — which means a newly added PHI table is locked out by default rather than briefly exposed during the gap between schema deploy and policy deploy.
Live in production today
The same engineering, shipped in production at BFEAI.
I'm co-founder & CTO of Be Found Everywhere (BFEAI), a 7-app AI SaaS platform running today. The work I deliver for clients is the work I do every week on my own platform.
7
Production apps
200K+
Keywords generated
1,500+
AI scans run
7,000+
Sites automated
Common questions
What buyers ask before reaching out
Should each clinic be its own tenant, or each provider, or each patient?
For most telehealth SaaS, the clinic (or practice group) is the tenant — that is the level at which billing, BAAs, and clinical accountability sit. Providers are users within a tenant with roles that scope what they can see. Patients are records inside the tenant. The shape that breaks is per-provider tenancy on a multi-provider clinic, because it scatters one clinic's PHI across N tenant boundaries and makes coverage handoffs an engineering problem instead of a workflow. The shape that also breaks is per-patient tenancy, which has the same scattering problem at a higher cardinality.
Does HIPAA actually require database-level tenant isolation, or is application-level enough?
HIPAA does not specify a layer. 45 CFR 164.312(a) requires access controls and unique user identification; 164.312(b) requires audit controls. The Security Rule is technology-neutral on how you implement them. The reason database-level isolation matters for telehealth multi-tenancy is not that the regulation names it — it is that application-only isolation puts the entire PHI boundary on the discipline of every engineer writing every query, and the cost of one wrong query is a breach notification under 164.408. Database-level RLS makes the wrong query return zero rows instead of another tenant's PHI.
What does the audit log have to capture for 164.312(b)?
The Security Rule requires mechanisms that record and examine activity in systems containing ePHI — in practice that means who accessed which record, when, and what action they took (view, create, modify, delete, export). For a multi-tenant telehealth app, the audit table has to capture tenant_id, actor user_id, target record reference, action type, and timestamp on every PHI read or write, and the storage has to be append-only so a compromised account cannot rewrite history. Retention horizon comes from your BAA chain and applicable state law, commonly six years.
How does the BAA boundary work when multiple tenants share infrastructure?
Shared infrastructure is fine under HIPAA if the underlying provider signs a BAA covering the workload — AWS, GCP, Azure, Supabase, and others have HIPAA-eligible offerings. The architectural question is which services you actually route PHI through, because each one has to be inside the BAA. Multi-tenant isolation reduces blast radius but does not remove the BAA obligation; a logging service that ingests query patterns containing PHI fragments is inside the boundary even if you did not plan for it to be. Keeping PHI in named, BAA-covered systems and routing everything else (analytics, error tracking, marketing tools) opaque IDs is the practical pattern.
Encryption at rest versus encryption in tenant — what is the difference and which one do we need?
Encryption at rest is the cloud provider's storage-layer encryption — the disk is encrypted, the keys are managed by the provider, and it satisfies the 164.312(a) addressable encryption specification at a baseline. Encryption in tenant means application-layer encryption with per-tenant keys, so even a database operator with full read access sees ciphertext for tenants whose keys they do not hold. The trade-off is real: per-tenant encryption breaks indexed search on the encrypted columns and complicates analytics. For most telehealth SaaS, storage-layer encryption plus disciplined RLS is the right floor; per-tenant keys come in when an enterprise customer's contract requires it or when the threat model includes the database administrator.
We have clinics in multiple states with different data residency rules. How does multi-tenancy handle that?
Tenant placement becomes a configuration concern instead of a schema concern. The application reads a tenant's region from the tenants table and routes data operations to the database (or schema, or partition) for that region. Cross-tenant queries become cross-region queries, which are explicitly forbidden at the policy layer — there is no clinical reason for tenant A in one state to be in the same query as tenant B in another. The architecture lets you add a region without rewriting the data model; the new region gets its own database instance and the tenants table records the placement.
What happens if a clinician changes clinics — does their account move or get recreated?
A new membership in the new clinic's tenant, with the old membership terminated rather than deleted (deletion would lose audit-log linkage). The user_id persists across clinics; the tenant_id and role on the membership change. RLS policies read the tenant scope from the current session claim, so the same human signing into a different clinic sees only that clinic's records. The audit log retains the prior tenant's activity under the same user_id, which is correct — 164.312(a)'s unique user identification requirement is satisfied at the human level, not the tenancy-membership level.
How long does a telehealth multi-tenancy engagement run?
Three to five weeks is typical for a seed or Series A telehealth SaaS, scoped against the EHR integration, the BAA chain, and whether you are greenfield or refactoring. Refactoring an app with live PHI takes longer because the migration has to run with the same audit and isolation discipline as the steady state — you cannot copy PHI rows across a non-HIPAA debugging session because the migration script does not have RLS. The scoping conversation usually starts with which systems already hold PHI and which ones are claiming they do not but actually do.
Ready to see if this is a fit?
A 15-minute call. No deck, no slides. We talk about what you're shipping and where engineering is the bottleneck. Either way, you walk away with a senior engineer's read on your situation.