Chapter 17 · Security, Privacy, Governance, and Auditability

Tenant Isolation and Ownership Boundaries

Model tenant ownership explicitly and compare shared-schema, separate-schema, and separate-database isolation patterns while preventing cross-tenant access.

Beginner75–105 minutesMulti-tenancy + isolationLast reviewed: August 2026

Learning outcomes

In a multi-tenant application, many customer organizations share one software platform. The database must preserve a critical invariant: one tenant must not read, modify, or infer another tenant's data unless explicitly authorized. Tenant isolation must be visible in keys, foreign keys, indexes, queries, and authorization rules.

01

Compare database-per-tenant, schema-per-tenant, and shared-schema designs.

02

Model tenant_id as part of ownership.

03

Prevent cross-tenant foreign-key and uniqueness mistakes.

04

Design defense-in-depth with row-level security and testing.

Three common isolation models

PatternIsolationOperational cost
Database per tenantStrong physical/logicalHigh at many tenants
Schema per tenantStrong namespace isolationMigration complexity
Shared tables + tenant_idLogical/policy isolationOperationally efficient

Shared-schema baseline

model · example
Customer(  tenant_id,  customer_id,  ...)

Every tenant-owned row needs an unambiguous tenant owner.

Tenant ownership propagates

You can derive tenant ownership through joins, but storing tenant_id on hot child tables often simplifies isolation, partitioning, and indexing.

Composite keys for tenant safety

sql · example
PRIMARY KEY (tenant_id, customer_id)FOREIGN KEY (tenant_id, customer_id)REFERENCES Customer(tenant_id, customer_id)

This prevents a row from pairing tenant A with customer_id belonging to tenant B.

Cross-tenant integrity

A foreign key on customer_id alone may be structurally valid yet insufficient for tenant ownership.

Global surrogate IDs

If customer_id is globally unique, tenant_id may not be needed in the PK, but tenant ownership still needs enforcement. Options include composite unique constraints and tenant-aware FKs.

Tenant-scoped uniqueness

model · example
UNIQUE (tenant_id, work_order_number)UNIQUE (tenant_id, sku)

allows different tenants to use the same business code while preserving uniqueness inside each tenant.

Global uniqueness when required

Some values, such as externally issued tokens or shared infrastructure names, may need global uniqueness. Do not mechanically prefix every constraint with tenant_id; choose the domain scope.

Tenant-aware indexes

model · example
(tenant_id, customer_id)(tenant_id, status_code, opened_at)

Tenant-first indexes often align with application predicates and keep access inside one tenant range.

Always scope queries

Dangerous:

sql · example
SELECT * FROM work_orderWHERE work_order_id = :id;

Safer:

sql · example
SELECT * FROM work_orderWHERE tenant_id = :tenant  AND work_order_id = :id;

Row-level security

A DB policy can add another layer:

model · example
tenant_id = current_setting('app.tenant_id')

Exact syntax varies by DBMS. Connection-pool context must be set/reset safely.

Connection pooling hazard

If tenant context persists on a reused connection, the next request can inherit the wrong tenant. Context-setting and cleanup must be deterministic.

Background jobs

Jobs often process many tenants. They need explicit tenant iteration and should not bypass isolation accidentally just because they run with elevated credentials.

Support/admin access

Cross-tenant support access should be:

  • separate from normal tenant sessions;
  • strongly authorized;
  • audited;
  • time-limited where practical.

Tenant deletion/export

Explicit tenant_id makes:

shell · example
export tenant 17delete tenant 17reconcile tenant 17

far easier than discovering ownership indirectly across dozens of tables.

Partitioning by tenant

Large systems may partition or shard using tenant_id. This can improve locality and isolation but creates hot-tenant and rebalancing considerations.

Noisy-neighbor problem

Security isolation does not guarantee performance isolation. One tenant with extreme workload can consume shared CPU/I/O. Rate limits, resource governance, or separate placement may be needed.

WorkshopHub tenant model

EntityTenant rule
CustomerDirect tenant owner
AssetMust belong to Customer in same tenant
WorkOrderMust belong to Asset in same tenant
PartCould be tenant-local or global catalog—decide explicitly
TechnicianTenant-local, shared, or multi-tenant employment must be modeled intentionally

Isolation tests

Automate tests that attempt:

  • read A's row using B's session;
  • create B child referencing A parent;
  • update by ID without tenant predicate;
  • reuse pooled connection after tenant switch;
  • run export/delete for one tenant only.

Practice: cross-tenant FK

Asset owner

Customer IDs are only unique within each tenant. Asset stores tenant_id and customer_id. What FK should it use?

Review answer

Use a composite foreign key (tenant_id, customer_id) referencing the Customer key/unique constraint with the same columns. Referencing customer_id alone cannot distinguish tenants.

Summary and next lesson

Tenant isolation is a schema invariant, not just a WHERE-clause convention. Tenant-aware keys, foreign keys, indexes, scoped queries, row-level policies, and explicit admin pathways provide defense in depth. The next lesson turns to auditability and provenance.

References

  • DBMS documentation on row-level security and roles.
  • OWASP multi-tenant application security guidance.
  • Cloud/database architecture guidance for tenant isolation models.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.