Skip to main content

Tenant isolation and row-level security

Payofy serves multiple distinct applications and schools within a single shared database instance. Isolation between tenants relies on strict PostgreSQL Row Level Security (RLS).

Setting tenant context​

Every database transaction establishes tenant context before running queries:

SELECT set_config('app.tenant_id', '00000000-0000-0000-0000-000000000001', true);

The third argument (true) binds this setting exclusively to the current transaction. Once the transaction completes or rolls back, the variable resets immediately.

Enforcing security policies​

Tables containing tenant data enforce a restrictive RLS policy:

CREATE POLICY tenant_isolation_policy ON "merchants"
AS RESTRICTIVE
USING (tenant_id = NULLIF(current_setting('app.tenant_id', true), '')::uuid)
WITH CHECK (tenant_id = NULLIF(current_setting('app.tenant_id', true), '')::uuid);

Even if application code omits a WHERE tenant_id = ... clause, the database prevents access to rows belonging to other tenants.