For indie hackers and solo founders building B2B SaaS applications, architectural simplicity is survival. When customer organizations (tenants) sign up for your software, you must decide how to isolate and manage their data.
Choose an architecture that is too simple, and a customer might accidentally access another company’s data. Choose an architecture that is too complex (such as orchestrating hundreds of separate cloud database instances), and you will spend all your development hours writing deployment scripts and managing connection pool limits instead of shipping product features.
In this guide, we break down the three primary multi-tenancy models for relational databases (MySQL and PostgreSQL), evaluate their operational trade-offs, and show how indie developers inspect and maintain multi-tenant workloads effectively on macOS.
The Three Relational Multi-Tenancy Architectures
| Architecture Model | Isolation Level | Infrastructure Cost | Operational Complexity | Backup / Restore Granularity |
|---|---|---|---|---|
| 1. Shared Database + Discriminator Column | Logical (Row-level) | Lowest (Single DB) | Low (Handled via ORM / RLS) | Whole database only |
| 2. Shared Database + Multi-Schema (Postgres) | Logical (Schema-level) | Low (Single DB) | Medium (Search paths & migrations) | Per-schema dumps supported |
| 3. Database-per-Tenant | Physical (Complete isolation) | High (Multiple DBs/pools) | Very High (Requires orchestration) | Easy per-tenant restore |
1. Model 1: Shared Database with tenant_id Column (The Indie Default)
In this model, all customers share the same database and tables. Every table (e.g., projects, invoices, members) includes a tenant_id (or account_id) foreign key column.
SELECT * FROM invoices
WHERE tenant_id = 492
AND status = 'unpaid';
How to Prevent Data Leak Bugs: PostgreSQL Row-Level Security (RLS)
Relying solely on your application backend code to append WHERE tenant_id = ... to every query is risky. One forgotten filter can expose private customer records.
PostgreSQL solves this at the database engine level via Row-Level Security (RLS):
-- Enable RLS on the table
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;
-- Create policy checking the active tenant session variable
CREATE POLICY tenant_isolation_policy ON invoices
FOR ALL
TO application_role
USING (tenant_id = current_setting('app.current_tenant_id')::INT);
When your backend establishes a connection, it sets the session tenant:
SET LOCAL app.current_tenant_id = '492';
-- Now, SELECT * FROM invoices automatically returns ONLY tenant 492's rows!
2. Model 2: Multi-Schema Multi-Tenancy (PostgreSQL search_path)
In PostgreSQL, a single database can contain multiple isolated schemas (tenant_1, tenant_2, etc.).
When a request arrives, your application configures the schema search path:
SET search_path TO tenant_492, public;
The Trade-off:
- Pros: Eliminates the need for
tenant_idcolumns and simplifies per-customer data exports (pg_dump -n tenant_492). - Cons: Running schema migrations across 2,000 schemas requires looping through every schema, which can dramatically slow down deployments.
3. Inspecting and Managing Multi-Tenant Schemas in SQLOZ (macOS Native)
Managing multi-tenant data on the command line is notoriously difficult. Testing whether an RLS policy functions correctly requires switching sessions and manually verifying queries.
SQLOZ provides native macOS tooling tailored for multi-tenant SaaS developers:

Key Features for SaaS Founders:
- Instant Session Variable Injection: In the SQLOZ SQL Editor, quickly set
SET LOCAL app.current_tenant_id = 492;to test and verify that your RLS policies correctly isolate tenant data. - Global Database Search (
⌘⇧F): Search for a customer’s email or transaction UUID across all tenant tables and schemas in seconds. - Safety Gate: When troubleshooting a specific tenant’s data on production, SQLOZ’s Safety Gate intercepts any
UPDATEorDELETEthat lacks a restrictive clause, preventing catastrophic cross-tenant data overwrites. - Attended Row-Level Data Compare: Compare reference data between staging and production schemas to ensure lookup catalogs remain synchronized.
Summary
For full-stack indie hackers, starting with a shared database + PostgreSQL Row-Level Security (RLS) offers the ideal balance of low hosting costs, strong isolation guarantees, and minimal operational maintenance.
By pairing modern RLS policies with a native macOS database client like SQLOZ, solo founders can build secure, scalable B2B SaaS platforms with enterprise-grade data isolation.
To learn more about secure database practices, read our guide on How to Safely Run UPDATE and DELETE Queries Without Crashing Production and discover The Best macOS Database GUIs for Solo Developers & Indie Hackers.