Skip to main content
Multi-tenancy is one of the hardest problems in SaaS development. You need to isolate data so Company A never sees Company B’s, handle authentication across organizational boundaries, manage two levels of admin, scope every query to the current tenant, and prevent cross-tenant access even from buggy or malicious code. Most teams spend weeks building this. Feather provides it out of the box — choose multi-tenant when you run feather new.

How it works

Feather uses domain-based tenant isolation. When a user signs in with bob@acme.com:
1

Extract the domain

Feather reads acme.com from the email.
2

Match a tenant

It looks up the tenant registered to that domain.
3

Assign the user

The user is attached to that tenant.
4

Scope every query

All subsequent queries are scoped to it.

Public email domains

By default Gmail, Outlook, Yahoo and other consumer providers are blocked — users must sign in with their work email. For B2B and B2C apps that support both:
.env
Users with public emails are then created with tenant_id=None. Use the post-login callback to handle account and tenant creation for them.

The two-axis authority model

Feather separates tenant authority — what you can do within your organization — from platform authority, cross-organization operator power.
Tenant admins do not bypass tenant isolation. An admin at Acme Corp cannot access data from Beta Inc. That requires explicit platform admin privileges.

Tenant admin

Approves and suspends users in their tenant, changes roles within it, views error logs scoped to it. Cannot see other tenants or their data.

Platform admin

Creates tenants and assigns domains, approves and suspends tenants, views all users and platform-wide analytics. Granted only via CLI, never the web UI.
Granting platform admin

Admin pages in multi-tenant mode

Data isolation, enforced at three layers

get_current_tenant_id() returns the authenticated user’s tenant.
require_same_tenant() is a hard stop — even tenant admins cannot bypass it. Cross-tenant operations require platform admin routes with explicit @platform_admin_required decorators.
feather check reports a query on a tenant-scoped model with no tenant filter as the tenant-isolation error, so a missed filter fails CI rather than leaking data.

The Tenant model

The scaffolded model supports both B2B (domain-based) and B2C (individual) patterns.
  • B2B tenants — set domain to auto-assign users by email
  • B2C tenants — leave domain as None and create individually via the post-login callback
  • type — classify tenants for billing, features or reporting

Tenant lifecycle

1

Platform admin creates the tenant

Via /admin/tenants. Sets name, slug and optionally an email domain, creates the initial tenant admin (auto-approved). The tenant starts pending.
2

Platform admin approves the tenant

The tenant becomes active.
3

Users sign up with a matching email domain

They are auto-assigned to the tenant and created in a suspended state.
4

Tenant admin approves the users

Via /admin/users.
This flow gives you both a platform-level and a tenant-level approval gate.