Row-level security filtert databaserijen op gebruikersrechten direct in PostgreSQL en is onmisbaar voor multi-tenant SaaS. Van tenant-isolatie via policies en RBAC-integratie tot Supabase RLS-configuratie: leer hoe RLS dataveiligheid afdwingt op infrastructuurniveau.
Row-Level Security (RLS) is een ingebouwde databasefunctie in PostgreSQL die op rijniveau bepaalt welke data een gebruiker mag lezen, aanmaken, wijzigen of verwijderen. Via declaratieve policies worden toegangsregels per tabel gedefinieerd die automatisch en transparant worden afgedwongen bij elke query, ongeacht de bron van het verzoek. RLS werkt op databaseniveau, volledig onafhankelijk van de applicatiecode, waardoor het een fundamentele verdedigingslaag vormt voor dataisolatie in multi-tenant SaaS-applicaties en compliance met privacywetgeving als de AVG.

Row-Level Security (RLS) is een ingebouwde databasefunctie in PostgreSQL die op rijniveau bepaalt welke data een gebruiker mag lezen, aanmaken, wijzigen of verwijderen. Via declaratieve policies worden toegangsregels per tabel gedefinieerd die automatisch en transparant worden afgedwongen bij elke query, ongeacht de bron van het verzoek. RLS werkt op databaseniveau, volledig onafhankelijk van de applicatiecode, waardoor het een fundamentele verdedigingslaag vormt voor dataisolatie in multi-tenant SaaS-applicaties en compliance met privacywetgeving als de AVG.
RLS in PostgreSQL wordt geactiveerd per tabel met ALTER TABLE tablename ENABLE ROW LEVEL SECURITY. Zodra RLS is ingeschakeld, is de default-policy deny-all: geen enkele rij is zichtbaar tenzij er een expliciete policy bestaat die toegang verleent. Policies worden aangemaakt met CREATE POLICY en kunnen worden beperkt tot specifieke operaties: FOR SELECT, FOR INSERT, FOR UPDATE en FOR DELETE. Een typische multi-tenant policy filtert op tenant_id: CREATE POLICY tenant_isolation ON orders USING (tenant_id = current_setting('app.tenant_id')::uuid). Het USING-clause filtert welke rijen zichtbaar zijn, terwijl WITH CHECK valideert welke rijen mogen worden ingevoegd of gewijzigd. De gebruikerscontext wordt doorgaans ingesteld via SET LOCAL of set_config() aan het begin van elke request. In Supabase wordt de tenant_id automatisch afgeleid uit het JWT-token van de geauthenticeerde gebruiker. De auth.uid() functie retourneert de gebruikers-ID en auth.jwt() geeft toegang tot custom claims in het token. RLS integreert naadloos met Role-Based Access Control (RBAC). Policies kunnen condities combineren: een admin-rol ziet alle rijen, een gebruikersrol ziet alleen eigen data, en een viewer-rol ziet data van de gehele organisatie maar mag niets wijzigen. Dit wordt geimplementeerd via OR-condities of meerdere policies per tabel. Voor performance is het cruciaal dat de kolommen in RLS-policies geindexeerd zijn. Een policy op tenant_id zonder index op die kolom resulteert in een full table scan bij elke query. PostgreSQL past RLS-filters toe als extra WHERE-condities die door de query planner worden geoptimaliseerd samen met de originele query. De BYPASSRLS-privilege staat specifieke database-rollen toe om RLS te omzeilen, wat nodig is voor administratieve taken als migraties, data-exports en achtergrondprocessen. In Supabase is dit de service_role key die uitsluitend server-side mag worden gebruikt. Voor complexe autorisatiescenario's kunnen policies gebruikmaken van subqueries en functies. Een policy kan controleren of een gebruiker lid is van een specifiek team via een subquery op de team_members tabel. Security definer functies encapsuleren complexe autorisatielogica die vanuit meerdere policies wordt hergebruikt. Dit voorkomt duplicatie en maakt het autorisatiemodel centraal beheerbaar vanuit een beperkt aantal functies.
MG Software implementeert RLS in elke multi-tenant SaaS-applicatie die we bouwen op Supabase. Onze standaardaanpak begint met het activeren van RLS op alle tabellen die tenantdata bevatten, gecombineerd met een default-deny policy die voorkomt dat nieuwe tabellen per ongeluk onbeschermd blijven na een migratie. Policies worden gebaseerd op de tenant_id die we opslaan als custom claim in het Supabase JWT-token. Bij authenticatie wordt de tenant-context automatisch beschikbaar via auth.jwt()->'tenant_id'. Dit elimineert de noodzaak om tenant-filtering in applicatiecode te implementeren en garandeert isolatie ongeacht hoe de data wordt benaderd. Voor beheertaken en achtergrondprocessen gebruiken we de Supabase service_role key die RLS omzeilt. Deze key wordt uitsluitend server-side gebruikt in beschermde API-routes en achtergrondprocessen, nooit in client-side code. Bij elke nieuwe tabel documenteren we de verwachte RLS-policies in het migratiescript en testen we deze met geautomatiseerde tests die queries uitvoeren vanuit verschillende gebruikerscontexten om cross-tenant lekken te detecteren.
Row-Level Security biedt een verdedigingslaag voor dataisolatie die onafhankelijk functioneert van de applicatiecode. In multi-tenant SaaS voorkomt RLS dat een bug, API-fout of verkeerde query per ongeluk data van andere tenants blootstelt. Dit is niet slechts een best practice maar een vereiste voor compliance met regelgeving als AVG/GDPR. Bij een beveiligingsaudit is RLS een concreet bewijsstuk dat dataisolatie op infrastructuurniveau is geimplementeerd. Zonder RLS is dataisolatie volledig afhankelijk van correcte WHERE-clausules in elke query van de applicatie. Een enkele vergeten filter in een nieuwe endpoint of een fout in een ORM-query kan leiden tot een datalek dat alle tenants treft. RLS verplaatst deze verantwoordelijkheid naar de database zelf, waar het consistent en automatisch wordt afgedwongen ongeacht hoe data wordt opgevraagd, of dat nu via de applicatie, een admin-tool of een directe databaseverbinding is.
Teams vergeten vaak RLS-policies te testen met verschillende gebruikerscontexten, waardoor permissielekken onopgemerkt blijven tot een beveiligingsaudit of incident. Schrijf geautomatiseerde tests die queries uitvoeren als gebruikers van verschillende tenants en valideer systematisch dat cross-tenant data onzichtbaar is voor zowel lees- als schrijfoperaties. Een tweede veelgemaakte fout is het niet instellen van een default-deny policy bij het activeren van RLS. Zonder expliciete default-deny zijn nieuwe tabellen zonder policies toegankelijk voor alle geauthenticeerde gebruikers. Stel altijd restrictive policies in als basis en verleen toegang alleen via expliciete GRANT-statements. Daarnaast worden performance-implicaties onderschat: policies op ongeindexeerde kolommen veroorzaken full table scans die de database progressief vertragen naarmate tabellen groeien. Voeg altijd een index toe op de kolom die in de RLS-policy wordt gefiltered.
Dezelfde expertise die u leest, zetten wij in voor klanten.
Ontdek wat wij kunnen doenAVG/GDPR uitgelegd: wat de privacywetgeving betekent voor uw software en organisatie
De AVG (GDPR) verplicht organisaties om persoonsgegevens van EU-burgers te beschermen via privacy by design, verwerkingsregisters en strenge beveiligingsmaatregelen. Ontdek de eisen, boetes en technische implementatie.
API Beveiliging in het kort: van definitie en best practices tot implementatie
API-beveiliging beschermt tegen injection, broken auth en overbelasting. Leer hoe input validatie, rate limiting, OAuth 2.0 en de OWASP API Security Top 10 uw endpoints en data beschermen tegen veelvoorkomende aanvallen en datalekken.
Multi-tenant architectuur: hoe tenant-isolatie werkt in de praktijk
Multi-tenant architectuur laat een enkele applicatie meerdere klanten bedienen met strikt gescheiden data. Ontdek hoe je tenant-isolatie implementeert met Row Level Security en shared databases voor schaalbare SaaS.
Software voor de financiele sector: fintech, compliance en veilige portals op maat
Versnel onboarding, rapportage en controles zonder compliance te verliezen. Teams rapporteren vaak 30 tot 50 procent minder handmatige uren op periodieke AML- en KYC-checks zodra workflows, data lineage en auditlogs in een platform zitten.