Multi-tenant Guide
Table of Contents
- Overview
- Configuration
- Data Isolation
- Tenant Management
- Authentication with Tenants
- Tenant-Specific vs Non-Tenant-Specific Roles
- Invitation System
- Tenant-Specific Permissions
- Schema Considerations
- Best Practices
Overview
Multi-tenancy in BAASIX allows you to host multiple separate client organizations (tenants) within a single instance of the application. Each tenant has their own isolated data, users, and permissions, while sharing the same underlying infrastructure and codebase.
Configuration
Enable multi-tenant mode by setting the appropriate environment variable:
# Enable multi-tenant functionality
MULTI_TENANT=true
# Define roles that are allowed for multi-tenant registration
# These are the roles that can be assigned when a user registers with a new tenant
ALLOWED_ROLES_MULTI_TENANT=user,customer,member
# Optional: Define the system field name for tenant identification
# Default is tenant_Id
TENANT_FIELD=tenant_IdData Isolation
When multi-tenant mode is enabled, BAASIX automatically:
- Adds a
tenant_Idfield to all non-system collections (tables that don't start withbaasix_) - Creates a relationship between each collection and the
baasix_Tenanttable - Modifies all unique constraints to be tenant-aware (unique per tenant rather than globally)
- Automatically filters all queries to only return data from the current tenant
Database Schema Changes
For each non-system collection, the following field is added:
"tenant_Id": {
"type": "UUID",
"allowNull": false,
"SystemGenerated": "true",
"description": "Tenant identifier for multi-tenant isolation"
},
"tenant": {
"relType": "BelongsTo",
"target": "baasix_Tenant",
"foreignKey": "tenant_Id",
"as": "tenant",
"SystemGenerated": "true",
"description": "M2O relationship to tenant"
}Tenant Management
Creating Tenants
Tenants can be created via the API:
POST /items/baasix_Tenant
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"name": "Organization Name",
"code": "org-code",
"settings": {
"brandColor": "#ff0000",
"maxUsers": 100
// Any tenant-specific settings
}
}Listing Tenants
GET /items/baasix_Tenant
Authorization: Bearer <admin_token>Updating Tenants
PATCH /items/baasix_Tenant/:id
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"name": "Updated Organization Name",
"settings": {
"brandColor": "#00ff00"
}
}Deleting Tenants
DELETE /items/baasix_Tenant/:id
Authorization: Bearer <admin_token>Authentication with Tenants
User Registration with Tenant
In multi-tenant mode, when registering a user, you must provide tenant information:
POST /auth/register
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"password": "securePassword123",
"tenant": {
"name": "New Tenant Organization"
}
}You can also specify an optional role if allowed by your configuration:
POST /auth/register
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"password": "securePassword123",
"tenant": {
"name": "New Tenant Organization"
},
"roleName": "user"
}Login with Tenant Selection
When logging in, you can optionally specify a tenant ID if the user has access to multiple tenants:
POST /auth/login
Content-Type: application/json
{
"email": "john@example.com",
"password": "securePassword123",
"tenant_Id": "550e8400-e29b-41d4-a716-446655440000"
}Switching Tenants
If a user has access to multiple tenants, they can switch between them:
POST /auth/switch-tenant
Authorization: Bearer <token>
Content-Type: application/json
{
"tenant_Id": "8a7d1ed4-8d7f-44b3-8f5e-7e5f2d8a7d3c"
}Getting Available Tenants
GET /auth/tenants
Authorization: Bearer <token>Tenant-Specific vs Non-Tenant-Specific Roles
BAASIX supports both tenant-specific and non-tenant-specific roles, which behave differently in a multi-tenant environment:
Tenant-Specific Roles
- Marked with
isTenantSpecific: true - Always associated with a specific tenant
- Can only access data within their assigned tenant
- Users with tenant-specific roles must specify or default to a tenant when logging in
POST /items/baasix_Role
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"name": "tenant_admin",
"description": "Administrator for a specific tenant",
"isTenantSpecific": true
}Non-Tenant-Specific Roles
- Marked with
isTenantSpecific: false - Not bound to any specific tenant
- Can potentially access data across tenants (subject to permissions)
- Users with non-tenant-specific roles can login without specifying a tenant
POST /items/baasix_Role
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"name": "global_admin",
"description": "Administrator with cross-tenant access",
"isTenantSpecific": false
}Handling Users with Multiple Roles
A user can have both tenant-specific and non-tenant-specific roles. In this case:
- If the user logs in without a specified tenant, the system will use their non-tenant-specific role
- If the user logs in with a specific tenant ID, the system will use their tenant-specific role for that tenant
Invitation System
BAASIX provides a comprehensive invitation system designed specifically for multi-tenant environments, allowing tenant administrators to invite users to their tenant with appropriate roles.
Role-Based Invitation Permissions
Roles can be configured with permissions to invite users with specific roles:
PATCH /items/baasix_Role/:id
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"canInviteRoleIds": ["550e8400-e29b-41d4-a716-446655440000", "8a7d1ed4-8d7f-44b3-8f5e-7e5f2d8a7d3c"]
}The canInviteRoleIds array contains the IDs of roles that users with this role are allowed to invite.
Creating Invitations
Tenant administrators can create invitations for users to join their tenant:
POST /auth/invite
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"email": "newuser@example.com",
"role_Id": "4a7d1ed4-8d7f-44b3-8f5e-7e5f2d8a7d3c",
"tenant_Id": "8a7d1ed4-8d7f-44b3-8f5e-7e5f2d8a7d3c",
"link": "https://yourapp.com"
}Invitation Workflow
The invitation system supports both new and existing users:
-
For new users:
- Admin sends an invitation
- User receives email with a registration link
- User follows the link and registers with the provided invitation token
- User is automatically assigned to the specified tenant and role
-
For existing users:
- Admin sends an invitation
- User receives email with a link to accept the invitation
- User logs in and accepts the invitation
- User gains access to the new tenant with the specified role
- User can switch between tenants they have access to
Cross-Tenant User Management
Through the invitation system, a user can have access to multiple tenants with different roles in each tenant, allowing for flexible cross-tenant user management while maintaining strict data isolation.
Tenant-Specific Permissions
Permissions in BAASIX are tenant-specific when multi-tenant mode is enabled. A user can have different roles and permissions across different tenants.
Assigning Role to User for Specific Tenant
POST /items/baasix_UserRole
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"user_Id": "550e8400-e29b-41d4-a716-446655440000",
"role_Id": "4a7d1ed4-8d7f-44b3-8f5e-7e5f2d8a7d3c",
"tenant_Id": "8a7d1ed4-8d7f-44b3-8f5e-7e5f2d8a7d3c"
}Creating Tenant-Specific Permissions
POST /permissions
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"role_Id": "4a7d1ed4-8d7f-44b3-8f5e-7e5f2d8a7d3c",
"collection": "products",
"action": "read",
"fields": "*",
"tenant_Id": "8a7d1ed4-8d7f-44b3-8f5e-7e5f2d8a7d3c"
}Schema Considerations
When creating schemas in multi-tenant mode, you don't need to manually define tenant fields - they are added automatically by BAASIX.
POST /schemas
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"collectionName": "products",
"schema": {
"name": "Product",
"timestamps": true,
"fields": {
"id": {
"type": "UUID",
"primaryKey": true,
"defaultValue": { "type": "UUIDV4" }
},
"name": {
"type": "String",
"allowNull": false
},
"price": {
"type": "Double",
"allowNull": false
}
// No need to define tenant_Id - it's added automatically
}
}
}Tenant-Aware Unique Constraints
When defining unique constraints in multi-tenant mode, the tenant_Id field is automatically included in the constraint, making values unique per tenant rather than globally:
POST /schemas/products/indexes
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"fields": ["sku"],
"unique": true,
"name": "sku_unique"
}In the database, this will actually create a constraint on ["sku", "tenant_Id"], allowing the same SKU to be used across different tenants but maintaining uniqueness within each tenant.
Best Practices
-
User Assignment: Always assign new users to at least one tenant. Users without tenant assignments won't be able to access most functionality.
-
Admin Users: Create super-admin users that have access across all tenants for system administration.
-
Cross-Tenant Access: For specific scenarios where cross-tenant access is needed, implement it through a system user with specific permissions.
-
Tenant Identification: Use descriptive names for tenants to make administration easier.
-
Tenant-specific Settings: Store tenant-specific settings in the
settingsJSON field of the tenant model. -
Tenant URL Patterns: Consider implementing tenant-specific subdomains or URL paths in your frontend application (e.g.,
tenant-name.yourdomain.comoryourdomain.com/tenant-name). -
Data Migration: When migrating data between tenants, ensure you update all tenant foreign keys correctly.
-
Hooks and Extensions: For hooks and extensions, check the tenant context to ensure operations are tenant-specific.
-
Performance: Be aware that queries in multi-tenant mode have an additional tenant filter which may affect performance on very large data sets.
-
Backup Strategy: Consider tenant-specific backup strategies for critical tenant data.
-
Role Management: Clearly distinguish between tenant-specific and non-tenant-specific roles in your application's UI.
-
Invitation Management: Implement proper UI flows for users to manage their tenant affiliations and accept invitations.
By leveraging BAASIX's multi-tenant capabilities, you can efficiently serve multiple client organizations from a single deployment, reducing infrastructure costs while maintaining strict data isolation between tenants.
Related Documentation
- Authentication Routes - User authentication with tenant support
- Permission Routes - Tenant-specific permissions
- Schema Reference Guide - Data model definitions