Why Supabase for Multi-Tenant SaaS?
After building three SaaS products on Supabase (EventRipple, PortLink, and a client project), I've developed strong opinions about multi-tenant architecture on the platform.
Supabase gives you PostgreSQL with batteries included: auth, real-time subscriptions, storage, and edge functions. For multi-tenant SaaS, the killer feature is Row-Level Security (RLS) — database-level tenant isolation that's impossible to bypass from application code.
Pattern 1: Shared Database, RLS Isolation
This is our default pattern. All tenants share the same tables, with RLS policies enforcing isolation.
-- Every table has an org_id column
ALTER TABLE events ADD COLUMN org_id UUID REFERENCES organizations(id);
-- RLS policy: users can only see their org's data
CREATE POLICY "tenant_isolation" ON events
FOR ALL
USING (org_id = (SELECT org_id FROM user_profiles WHERE id = auth.uid()));
Pros
- Simple schema, easy to maintain
- Efficient queries (shared indexes)
- Easy cross-tenant analytics (for you, not tenants)
Cons
- Noisy neighbor risk (one tenant's heavy queries affect others)
- Backup/restore is all-or-nothing
Pattern 2: Schema-Per-Tenant
For high-isolation requirements, create a PostgreSQL schema per tenant.
CREATE SCHEMA tenant_abc123;
CREATE TABLE tenant_abc123.events (LIKE public.events_template INCLUDING ALL);
We use this for PortLink where maritime companies require strict data isolation for compliance reasons.
Pattern 3: Real-Time Subscriptions
Supabase real-time is powerful but needs careful filtering in multi-tenant contexts.
const channel = supabase
.channel('events')
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'events',
filter: `org_id=eq.${orgId}`,
}, handleChange)
.subscribe();
Critical: Always filter by tenant ID in subscriptions. Without this, you'll receive changes from ALL tenants (RLS doesn't apply to real-time by default in older versions).
Lessons Learned
- Always enable RLS — even in development. Finding RLS bugs in production is painful.
- Test with multiple tenants from day one. Single-tenant testing hides isolation bugs.
- Use Supabase CLI for migrations. Never modify production schemas manually.
- Monitor query performance per tenant. One bad query pattern can affect everyone.
Based on production experience with Supabase across EventRipple, PortLink, and client projects.