Skip to main content

Overview

SuperTokens Core provides enterprise-grade multi-tenancy support, allowing you to serve multiple customers (tenants) from a single SuperTokens instance. Each tenant can have isolated data, custom configurations, and independent authentication settings.

Architecture

Hierarchy

SuperTokens uses a three-level hierarchy:
1

Connection URI Domain

Top-level identifier, typically maps to a database connection
2

App

Application within a connection URI domain, shares a user pool
3

Tenant

Individual tenant within an app, can have custom configuration

Tenant Identifier

Every operation is scoped to a TenantIdentifier:
The default tenant is represented as TenantIdentifier(null, null, null) which resolves to ("", "public", "public").

Creating Tenants

Tenant Configuration

From io/supertokens/multitenancy/Multitenancy.java:231-318:

Tenant Config Structure

TenantIdentifier
required
Unique identifier for the tenant
JsonObject
Tenant-specific core configuration overrides
ThirdPartyConfig
OAuth/OIDC provider configurations for this tenant
EmailPasswordConfig
Email/password specific settings
PasswordlessConfig
Passwordless authentication settings

Permission Model

From io/supertokens/multitenancy/Multitenancy.java:63-126:

Create/Update Permissions

Tenant Level

Use public tenant or same tenant

App Level

Use public tenant of the app

CUD Level

Use base tenant or same CUD

Delete Permissions

Only parent entities can delete children:
  • Parent app can delete tenants
  • Parent CUD can delete apps
  • Base tenant can delete connection URI domains

User Management

User-Tenant Association

Users can be associated with multiple tenants:

Conflict Prevention

From io/supertokens/multitenancy/Multitenancy.java:396-555: When associating a primary user with a tenant, SuperTokens checks:
1

Email Uniqueness

No other primary user in the tenant has the same email for the same recipe
2

Phone Number Uniqueness

No other primary user in the tenant has the same phone number
3

Third-Party Uniqueness

No other primary user has the same third-party ID + third-party user ID
These checks only apply to primary users. Recipe users without account linking can have duplicate identifiers across tenants.

Disassociating Users

Storage Architecture

Database Isolation Models

SuperTokens supports multiple storage models:

Shared Database

All tenants in one database with tenant_id columns

Separate Databases

Each tenant has its own isolated database

Hybrid

Mix of shared and isolated based on tier

Tenant Storage Mapping

Tenants within the same app share a user pool:

Configuration

Core Configuration Overrides

Tenants can override most core configurations:
Protected configs cannot be changed after tenant creation:
  • Database connection parameters
  • Core service ports
  • Base paths
From io/supertokens/multitenancy/Multitenancy.java:158-180:

Third-Party Provider Configuration

Each tenant can have independent OAuth/OIDC providers:

Listing Tenants

All Tenants

Tenants for an App

Tenants for Connection URI Domain

Deleting Tenants

Delete a Tenant

From io/supertokens/multitenancy/Multitenancy.java:320-335:
Deleting a tenant does not delete user data. You must explicitly delete users before deleting the tenant.

Delete an App

From io/supertokens/multitenancy/Multitenancy.java:337-357:

API Domain Configuration

Store per-app website and API domains:

Feature Flag Requirement

Multi-tenancy requires the MULTI_TENANCY feature flag to be enabled:

Use Cases

B2B SaaS

Each customer gets their own tenant with isolated data and branding

White-Label Apps

Different apps for different brands using the same codebase

Regional Isolation

Separate tenants for different geographic regions

Development Environments

Separate tenants for dev, staging, and production

Best Practices

  1. Use Meaningful IDs: Choose descriptive tenant IDs like customer-acme instead of UUIDs
  2. Plan User Pool Boundaries: Users within an app share a pool - plan accordingly
  3. Minimize Config Overrides: Only override what’s necessary per tenant
  4. Handle Tenant Not Found: Always catch TenantOrAppNotFoundException gracefully
  5. Use Public Tenant for Global Operations: Store app-wide settings in the public tenant