Vicedomini Softworks

Software Security

Shared Schema and RLS: Multi-Tenant Data Isolation for Architects

11 September 2026

Shared Schema and RLS: Multi-Tenant Data Isolation for Architects

Shared schema, tenant_id, and PostgreSQL row-level security should be the default architecture for most B2B SaaS platforms. This combination balances cost, operational simplicity, and defence-in-depth security. Reach for schema-per-tenant or database-per-tenant only when regulation, very large accounts, or bring-your-own-key demands force it, and treat full-stack tenant-context hygiene, across caches, queues, and logs, as mandatory regardless of which model you pick.


TL;DR:

  • Using shared schema with row-level security is recommended as the default architecture for most SaaS platforms, balancing cost and security when properly enforced.
  • Proper implementation requires enabling force row-level security, setting tenant context with transaction-scoped settings, and including tenant_id in indexes and foreign keys for fast, tenant-specific queries.
  • Outside the database, tenant hygiene must be maintained in caches, object storage, message brokers, and logs, using tenant-specific prefixes, ACLs, and policies to prevent data leakage.
  • To mitigate noisy neighbor issues, implement rate limiting, circuit breakers, and sharding, and consider dedicated infrastructure for heavy or regulated tenants.
  • Moving to stronger isolation models like schema-per-tenant or database-per-tenant is advisable only when specific triggers such as high resource consumption or compliance demands occur.

Vicedomini Softworks
vicedominisoftworks.com
Engineer A Safer SaaS Foundation
Vicedomini Softworks designs scalable SaaS platforms, backend systems, and integrations with direct collaboration from discovery through ongoing support.
Explore custom software solutions

Table of Contents

What are the levels of multi-tenant data isolation?

Isolamento dati multi tenant sits on a spectrum, not a binary switch. At one end, every tenant shares the same tables, rows tagged by tenant_id. At the other, each tenant gets a dedicated database instance with no shared infrastructure at all. Microsoft’s architecture guidance frames this explicitly as a spectrum of storage and data options, from shared containers through schema-per-tenant to full database-per-tenant, and AWS uses similar language with its Silo, Bridge, and Pool models in multi-tenant architecture guidance.

The trade-offs move in lockstep as you climb that spectrum:

  • Pooled (shared schema): lowest cost, highest density, weakest native isolation, relies entirely on application and database policy enforcement.
  • Bridge (schema-per-tenant): moderate isolation, easier to reason about per-tenant backups, but migrations multiply linearly with tenant count.
  • Silo (database-per-tenant): strongest isolation, simplest compliance story, but the most expensive to operate at scale and the hardest to keep consistent across schema versions.

A useful decision rule: with a moderate number of tenants who have broadly similar compliance needs, pooled architecture with strict policy enforcement often wins on cost and velocity. Once you have regulated tenants, enterprise clients demanding dedicated infrastructure, or workloads whose resource consumption varies wildly between accounts, silo or bridge models earn their operational overhead.

Which database pattern fits shared, schema, and silo models?

Each pattern carries its own implementation discipline. Get the details wrong and the isolation boundary you think you have is not the one you actually have.

For shared schema plus row-level security, treat the following as a non-negotiable checklist:

  1. Enable FORCE ROW LEVEL SECURITY on every tenant-scoped table, not just ENABLE, so even table owners and migration roles respect the policy.
  2. Set tenant context with SET LOCAL inside the transaction, never as a session-wide setting, so pooled connections cannot leak context between requests.
  3. Lead every composite index and foreign key with tenant_id, which keeps tenant-scoped queries fast and prevents full-table scans that masquerade as noisy-neighbour problems.
  4. Include tenant_id in composite foreign keys so a row can never reference a parent belonging to a different tenant.

Practitioner guidance on designing database isolation for B2B SaaS treats RLS as the safety net underneath application-level filtering, not a replacement for it. Connection pooling is where this discipline usually breaks. PgBouncer in transaction mode can hand the same physical connection to two different tenants’ requests within milliseconds. If tenant context is set at the session level rather than scoped to the transaction, that second request inherits the first tenant’s permissions.

Pro Tip: Run a test that opens a transaction, sets the tenant GUC, deliberately forgets to reset it, and commits. If your pooler configuration lets the next transaction on that connection see the previous tenant’s rows, you have found your leak before a real tenant does.

Schema-per-tenant becomes pragmatic once a handful of tenants need genuinely separate backup and restore cycles, but understand the cost: every migration must run against every schema, and drift between schemas becomes a silent operational hazard. Database-per-tenant needs a tenant registry mapping tenant IDs to connection strings, and lazy, service-side pooling rather than a permanently warm connection to every tenant database on every app instance, which is how connection counts explode past provider limits, a constraint Google Cloud’s Spanner multi-tenancy documentation calls out directly.

How do you keep tenant hygiene outside the database?

Multi-tenant data security fails as often outside the database as inside it. Caches, object storage, message queues, and log pipelines are where isolation boundaries quietly evaporate if nobody designs for them deliberately.

  • Caching: prefix every Redis key with tenant_id, and back that with ACLs or dedicated endpoints for high-value tenants. Logical database separation inside Redis is not a security boundary. Any client with the connection string can select any logical database, so treat it as a convenience feature, not a control, a distinction Redis’s own guidance on multi-tenant data isolation makes explicit.
  • Object storage: per-tenant prefixes work for low-sensitivity data, but regulated or enterprise tenants usually need per-tenant buckets or storage accounts with IAM policies that make cross-tenant access structurally impossible, not merely unlikely.
  • Message brokers: scope topics per tenant, apply broker-level ACLs, and enforce per-client publish and consume quotas so one tenant’s burst traffic cannot starve another’s consumers.
  • Logging and analytics: index-per-tenant with access controls prevents a support engineer debugging Tenant A’s ticket from stumbling into Tenant B’s log lines, and it lets you apply separate retention policies where contracts demand it.

How do you stop one tenant degrading performance for others?

The noisy-neighbour problem is one of the most common failure modes in shared infrastructure. Microsoft’s antipattern documentation describes it precisely: a single tenant’s workload consumes disproportionate shared resources and degrades service for everyone else on the same infrastructure.

Mitigation happens at several layers simultaneously:

  • Rate limiting and per-tenant quotas at the API gateway, enforced before requests reach application logic.
  • Circuit breakers that isolate a failing or overloading tenant’s traffic rather than letting it cascade.
  • Sharding or horizontal partitioning so heavy tenants land on infrastructure separate from the bulk of your pooled base.
  • Per-tenant telemetry and service-level objectives, with alerting tuned to catch one account’s resource curve bending away from baseline.

Pro Tip: You do not need a full migration to isolate a heavy tenant. Route their traffic to a dedicated read replica or a separate connection pool while keeping the same schema. It buys time to plan the real migration without an emergency.

What security controls actually enforce tenant boundaries?

Encryption in transit and at rest is the floor, not the differentiator. What separates adequate multi-tenant database privacy from enterprise-grade security is how identity and key management enforce the boundary at every layer.

  • Embed tenant context directly in authentication tokens, and re-verify it on every authorisation decision, never trust a token’s claims from three requests ago.
  • Offer per-tenant encryption keys or bring-your-own-key (BYOK) arrangements for tenants that demand it contractually. This is often the deciding factor in enterprise negotiations, and it is operationally simplest to deliver under a database-per-tenant model, where key rotation and scoping map cleanly to infrastructure boundaries.
  • Recognise that your data-layer choice constrains your key-management options. Per-tenant keys are straightforward with silo architecture and considerably harder to retrofit onto a shared schema without re-architecting storage.
  • Maintain audit trails for every access to tenant data, and keep migration or operations roles from silently bypassing RLS policies, a common blind spot when a “superuser” database role runs routine maintenance scripts.

Compliance frameworks such as GDPR, HIPAA, and SOC 2 are outcome-based rather than architecture-prescriptive. None of them mandate database-per-tenant, but contracts often do, and that distinction is worth understanding before you over-engineer isolation nobody is actually requiring. For teams building out the identity and access side of this, AtListen’s guidance on access control and encryption and IT Start’s data encryption explainer both cover KMS mechanics worth reviewing alongside your own key-rotation policy.

When should you move to stronger isolation?

Watch for concrete triggers rather than waiting for a crisis: sustained CPU or IO usage from a single tenant well above baseline, latency complaints traced to one account’s query patterns, connection limits approaching capacity, or a compliance requirement that simply forbids shared infrastructure.

  1. Dual-write the tenant’s data to both old and new locations during transition, verifying consistency before cutover.
  2. Route connections through a tenant registry mapping tenant IDs to destination DSNs, which lets you migrate without forking application code.
  3. Stage the rollout tenant by tenant, with versioned migrations and a tested per-tenant rollback path before you touch the next account.

How do you test and verify tenant isolation?

Automated tests must cover both the API path and raw SQL access, because a policy that blocks the ORM but not a direct query is not a policy. Run tests that attempt cross-tenant reads and writes through every entry point, including background jobs and scheduled tasks, which architects frequently under-estimate as leak vectors when tenant context never gets stamped into the job payload.

  • RLS and policy enforcement tests that deliberately attempt cross-tenant access and expect a hard failure.
  • Chaos tests simulating a single tenant’s load spike to confirm quotas and circuit breakers hold.
  • Backup, restore, and per-tenant export/delete tests, essential for honouring deletion requests under GDPR without touching other tenants’ data.

Statistic Callout: Missing tenant context in background workers and raw SQL paths is one of the most frequently cited real-world causes of cross-tenant leaks in practitioner guidance on multi-tenant isolation, precisely because these paths sit outside the request middleware that normally sets tenant context.

How does Vicedomini Softworks approach tenant isolation engineering?

Vicedomini Softworks applies the same engineering discipline to tenant isolation that it applies across its custom software work: peer-reviewed code, infrastructure automation, and Zero Trust security principles baked into architecture decisions from day one, not retrofitted after a leak. On cloud-native builds powered by Red Hat OpenShift, tenant boundaries get enforced through Kubernetes-level policy alongside database controls, giving clients layered protection rather than a single point of failure. Support spans architecture review, migration planning between isolation models, and ongoing observability once the system is live, work grounded in direct engineer-to-client collaboration rather than a managed layer of account intermediaries.

How does Vicedomini Softworks approach tenant isolation engineering? — overview diagram

What actually matters when you choose an isolation model

Start with shared schema and RLS. It is the right default for nearly every early and mid-stage B2B SaaS platform, and graduating individual heavy or regulated tenants to dedicated infrastructure later is far easier than unwinding an over-engineered silo model you built for tenants that never materialised. Compliance and sales requirements should override engineering simplicity when a signed contract demands dedicated infrastructure, not before. The single most common mistake is not architectural at all: developers forget to propagate tenant context into background jobs and raw SQL, quietly reopening the boundary the RLS policy was supposed to close.

— Pepe F.

How Vicedomini Softworks supports your isolation architecture

Getting isolamento dati multi tenant right, under deadline pressure, is where most teams either over-build or under-protect. Collaboration directly with engineers designing your system, without an account-manager layer translating requirements, means architecture decisions on tenant boundaries get made by the people who also build and maintain them.

Vicedomini Softworks

Typical engagements start with an architecture audit of your current or planned data model, move into a proof-of-concept validating the isolation approach against your actual compliance and scale requirements, and proceed through a phased migration with observability and security engineering built in from the first sprint. That covers architecture review, cloud-native implementation on infrastructure like Red Hat OpenShift, connection-routing and migration work for teams graduating tenants between models, and the monitoring needed to catch a noisy-neighbour problem before a client notices it. If your platform is approaching the point where a shared-schema model needs stronger guarantees for specific tenants, get in touch through the services page and start with an architecture review.

Sources

FAQ

What is multi-tenant isolation?

Multi-tenant isolation is the set of architectural and operational controls that prevent one customer’s (tenant’s) data, performance, or configuration from being accessible to or affected by another tenant sharing the same software platform.

What are the disadvantages of multi-tenancy?

Shared infrastructure introduces noisy-neighbour risk, where one tenant’s load degrades others, and it demands rigorous policy enforcement (like RLS) because the database no longer provides isolation by default the way separate databases do.

What is considered a multi-tenant system?

A system is multi-tenant when a single deployed instance of the application and its underlying infrastructure serves multiple distinct customers, each with logically separated data and configuration rather than a dedicated instance per customer.

How do you set up multi-tenancy correctly?

Start with a shared schema using a tenant_id column, enforce PostgreSQL row-level security with FORCE RLS and transaction-scoped context, and layer tenant-aware hygiene across caches, storage, and queues before considering schema or database-per-tenant models.