All Docs
FeaturesPosibl Life & Gym AppUpdated March 13, 2026

Multi-Tenant Schema & Row-Level Isolation

Multi-Tenant Schema & Row-Level Isolation

The platform is built on a multi-tenant architecture where every gym (tenant) operates in complete data isolation from all other gyms on the platform. This page explains how tenancy is structured, how data isolation is enforced, and how cross-tenant features work within those constraints.


Tenant Hierarchy

The platform models a real-world fitness business hierarchy. From the top down:

LevelRoleDescription
1Platform OwnerThe SaaS operator managing the entire platform
2Affiliate GymAn individual gym business (a tenant)
3CoachA staff member who authors and delivers programming
4Personal Trainer (PT)A trainer who manages individual member relationships
5MemberAn athlete who trains, tracks progress, and engages with the community

Every entity from level 2 downward belongs to exactly one affiliate gym (tenant) and is tagged with that gym's tenant_id.


Data Isolation via Row-Level Security

Data isolation is enforced at the database layer using Postgres Row-Level Security (RLS), not the application layer.

How it works

  1. Every table in the schema has a tenant_id column.
  2. RLS policies are applied to all tenant-scoped tables using CREATE POLICY.
  3. At the start of each database session, the current tenant context is set (e.g. via a session variable or connection parameter).
  4. Postgres automatically filters all SELECT, INSERT, UPDATE, and DELETE operations through the RLS policy — a query from Tenant A will never touch rows belonging to Tenant B, even if the application-layer query does not include an explicit WHERE tenant_id = ? clause.

Why database-layer isolation?

Enforcing isolation in the database rather than in application code means:

  • Accidental data leaks are prevented — a missing WHERE clause in application code cannot expose another tenant's data.
  • Security audits are simpler — the isolation boundary is in one place (the schema), not scattered across every query.
  • New features inherit isolation automatically — any new query against an RLS-protected table is automatically scoped to the current tenant.

Cross-Tenant Features

Some platform features operate across tenant boundaries by design — for example, platform-wide leaderboards or affiliate network visibility. These are supported through a shared schema layer that is separate from tenant-scoped tables.

Principles

  • Cross-tenant data access is explicitly opt-in — it only occurs through the shared schema, never by bypassing RLS on tenant tables.
  • The shared schema exposes only the data necessary for network features; full tenant records are never exposed across boundaries.
  • The platform owner has elevated privileges to query across the shared schema for operational and business intelligence purposes.

Schema Design Rules

All contributors working on database migrations must follow these rules to maintain isolation guarantees:

  1. Every new tenant-scoped table must include a tenant_id column of the appropriate type, with a NOT NULL constraint and a foreign key reference to the tenants table.
  2. RLS must be enabled and a policy must be created on every new tenant-scoped table before it is deployed to production.
  3. Cross-tenant data must only be surfaced through the shared schema layer — never by disabling or bypassing RLS on tenant tables.
  4. Test isolation — integration tests should verify that a query executed with one tenant's context cannot return rows belonging to another tenant.

Database

The platform uses Neon Postgres — a serverless, fully managed Postgres service. Neon's connection pooling and branching capabilities complement the multi-tenant architecture by allowing per-tenant connection contexts to be established efficiently.