What is Row Level Security?
RLS is a PostgreSQL feature that adds an implicitWHERE clause to every query based on policies you define. This means security is enforced at the database level, protecting your data even if accessed through third-party tools.
RLS works with Supabase Auth to provide end-to-end security from the browser to the database.
Why RLS is Critical
Tables in the
public schema without RLS enabled are accessible to anyone with your anon key.Supabase allows browser access to your database for convenience, but this requires RLS to be secure.- Defense in depth: Protection even if application code has vulnerabilities
- Automatic enforcement: No way to bypass security from client code
- Granular control: Different rules for SELECT, INSERT, UPDATE, DELETE
- Third-party protection: Security maintained when using external tools
Enabling RLS
Enable on Individual Tables
Auto-Enable RLS on New Tables
Create an event trigger to automatically enable RLS:This trigger only affects tables created after installation. Enable RLS manually on existing tables.
Creating Policies
Policies define the rules for accessing rows. Each policy has:- Table: Which table it applies to
- Operation: SELECT, INSERT, UPDATE, or DELETE
- Role: Which database role (anon, authenticated)
- Condition: SQL expression that must be true
SELECT Policies
Control which rows users can view:INSERT Policies
Control which rows users can create:WITH CHECK ensures the new row data meets policy requirements.UPDATE Policies
Control which rows users can modify:DELETE Policies
Control which rows users can delete:Common Policy Patterns
User-Owned Data
Team-Based Access
Role-Based Access
Multi-Factor Authentication Required
Helper Functions
auth.uid()
Returns the ID of the authenticated user:
auth.jwt()
Accesses JWT claims:
Performance Optimization
RLS policies can impact query performance. Follow these practices:1. Add Indexes
Index columns used in policies:2. Wrap Functions with SELECT
Improve function performance:Wrapping with
SELECT causes PostgreSQL to cache the function result per statement instead of calling it for each row.3. Add Filters to Queries
Even with policies, always filter in your queries:4. Use Security Definer Functions
Bypass RLS for complex joins:Never put security definer functions in schemas exposed via PostgREST (like
public). Use a private schema.5. Minimize Joins
Rewrite policies to avoid table joins:6. Specify Roles
Always useTO clause:
Testing RLS Policies
Manual Testing
Test as different users:Automated Testing with pgTAP
Bypassing RLS
Service Role Key
Theservice_role key bypasses all RLS:
Never use service_role key in client-side code! This gives unrestricted database access.Safe usage:
- Server-side code only
- Admin tools
- Background jobs
- Database migrations
Custom Roles with Bypass
Create roles that bypass RLS:Troubleshooting
No rows returned after enabling RLS
No rows returned after enabling RLS
Cause: RLS enabled but no policies createdSolution:
Policies not working as expected
Policies not working as expected
Cause: Multiple policies are combined with OR logicSolution:
- Check all policies on the table
- Use
RESTRICTIVEpolicies for AND logic - Test with specific roles:
SET ROLE authenticated
Performance issues
Performance issues
Cause: Missing indexes or inefficient policiesSolution:
- Add indexes on columns used in policies
- Wrap functions with
SELECT - Minimize table joins
- Use security definer functions
- Always add filters to queries
auth.uid() returns null
auth.uid() returns null
Cause: User not authenticated or token expiredSolution:
Best Practices
1
Enable RLS on all tables
Never leave tables in
public schema without RLS2
Start restrictive, then open up
Begin with policies that deny everything, then add access:
3
Test policies thoroughly
Test as different user types before deploying
4
Monitor performance
Use Performance Advisor to find slow policies
5
Document complex policies
Add comments explaining business logic
Next Steps
Encryption
Learn about data encryption in Supabase
Network Security
Configure IP restrictions and SSL
Testing Guide
Set up automated RLS testing
Performance Tuning
Optimize RLS policy performance
