Multi-Tenancy Architecture
Tonnex uses a Table-Based Multi-Tenancy approach with Row Level Security (RLS). Every tenant-specific table has anorg_id column that links to the organizations table.
Access is enforced at the database level using Postgres RLS policies.
Key Components
1. Organization Membership Check
We use aSECURITY DEFINER function to verify if a user belongs to an organization.
This bypasses RLS on the org_memberships table itself to avoid infinite recursion.
2. Drizzle Integration (Supabase)
We usedrizzle-orm/supabase helpers to define RLS policies directly in the schema.
3. RLS-Aware Client
When querying from the application (Server Actions/Components), we use a wrapper that sets the RLS context for the transaction.auth.uid()viarequest.jwt.claim.subauth.jwt()viarequest.jwt.claimsroleviaset local role
Adding a New Module
When creating a new module (e.g.,vehicles):
- Add
orgIdto your table schema. - Add the RLS policy usage
isOrgMember(table.orgId)for SELECT/UPDATE/DELETE. - Use the
createDrizzleSupabaseClientwrapper for all queries.