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.