Kizaki
Guides

Multi-Tenancy

Use namespaces and principal-derived scope to keep tenant data isolated by default.

For SaaS apps, the recommended path is to derive tenant scope from the authenticated principal and let namespaces enforce it automatically.

entity Organization {
  name: string,
  slug: string @unique,
}

entity Project {
  name: string,
  organizationId: Organization.id,
}

namespace Tenant {
  scope: principal.organizationId,
  entities: [Project],
}

Why Namespaces Matter

In a typical SaaS stack, developers remember to add tenant filters in some places and forget them in others. Namespaces change the model. Tenant scope is no longer a convention in application code. It becomes a platform-level rule applied everywhere the entity is used.

That means your app code can stay focused on product logic rather than repeating organizationId filters on every screen and server function.

Add The Scope To Principal

auth {
  providers: [email],

  principal {
    organizationId: Organization.id @from(Profile.organizationId),
  }
}

If users can switch organizations, the current organization should still become a single principal value for the request or session context. That keeps the rest of the app deterministic.

Result

Any query against Project now inherits tenant scoping. You do not manually thread tenant filters through every handler and browser query.

  • create an explicit top-level tenant entity such as Organization
  • use membership entities to connect users to tenants
  • project the current tenant into the principal
  • namespace the app entities that belong inside the tenant boundary

This is usually enough to support the first serious version of a SaaS product.

On this page