Two locks, and the hole PostgreSQL reserves for the owner
PostgreSQL lets a table's OWNER walk past its own row-level-security policies — unless you set FORCE ROW LEVEL SECURITY. And nothing stops a SUPERUSER. So tenant isolation is 2 locks, not 1.

The €100 Lakehouse — 7/12
PostgreSQL lets a table's OWNER walk past its own row-level-security policies — unless you set FORCE ROW LEVEL SECURITY. And nothing stops a SUPERUSER. So tenant isolation is 2 locks, not 1.
Hard rule since day zero: tenant_id is born at the source and never comes from a client. SSO claim → Superset RLS (lock 1) → Postgres native RLS (lock 2). If the app layer is compromised, Postgres still refuses another tenant's rows.
Each lock asserted by a test, not a diagram:
→ the serving role owns nothing and is member of nothing — pg_has_role asserted false
→ none of the 4 mart roles has rolsuper or rolbypassrls — asserted on all 4
→ the publisher cannot even DELETE or TRUNCATE the mart
Measured bonus: PUBLIC had CONNECT on every database of the shared RDS instance. Revoked on ours via migration, asserted by pgTAP. Revoking it on the platform's own DB? Filed as a platform-ask — never executed from our side.
The honest exception, written down: the RDS master can read everything. The instance's break-glass, never a serving path, not ours to change.
Defense in depth is only real when each lock is asserted by a test — including the list of what it can NOT close.
That's why tenant #2 is a template clone, not a build: isolation is structural, not procedural.
In your multi-tenant setup: if the application layer is compromised, what's the second lock — and has a test ever proven it?
Databricks · dbt · Airflow · Terraform · AWS
P.S. New tech post every Wednesday.
#100EuroLakehouse #PostgreSQL #MultiTenant
Comments