Multi-tenancy
Overview
ABP React implements a comprehensive multi-tenancy system that allows the application to serve multiple tenants while maintaining data isolation and tenant-specific configurations.
Tenant Resolution
Host-based Resolution
The application resolves tenants based on the host header:
export async function GET() {
const session = await getSession()
const host = (await headers()).get('host')
if (session.tenantId) {
return
}
try {
const { data } = await tenantGetTenantGuid({ query: { host: host! } })
session.tenantId = data ?? 'default'
} catch (error) {
session.tenantId = 'default'
}
await session.save()
redirect('/')
}
Tenant Management
Tenant List Component
The application provides a tenant management interface:
export const TenantList = () => {
// ... tenant list implementation
const defaultColumns: ColumnDef<TenantDto>[] = [
{
header: 'Tenant Management',
columns: [
{
accessorKey: 'actions',
header: 'Actions',
cell: (info) => {
return (
<PermissionActions
actions={[
{
icon: 'features',
policy: 'AbpTenantManagement.Tenants.ManageFeatures',
callback: () => {
// ... feature management
},
},
{
icon: 'pencil',
policy: 'AbpTenantManagement.Tenants.Update',
callback: () => {
// ... tenant update
},
},
]}
/>
)
},
},
],
},
]
}
API Integration
Tenant Context in Requests
The tenant context is automatically included in API requests:
APIClient.interceptors.request.use(async (options) => {
const session = await getSession()
options.headers.set('__tenant', session.tenantId ?? '')
return options
})
Tenant Features
Feature Management
Tenants can have specific features enabled/disabled:
interface TenantExtraProperties {
features?: {
[key: string]: boolean
}
}
Tenant Settings
Each tenant can have its own configuration:
- Custom domain
- Feature flags
- Connection strings
- Custom settings
Tenant Operations
Creating Tenants
const tenantCreate = async (data: TenantCreateDto) => {
return await APIClient.post('/api/multi-tenancy/tenants', data)
}
Updating Tenants
const tenantUpdate = async (id: string, data: TenantUpdateDto) => {
return await APIClient.put(`/api/multi-tenancy/tenants/${id}`, data)
}
Deleting Tenants
const tenantDelete = async (id: string) => {
return await APIClient.delete(`/api/multi-tenancy/tenants/${id}`)
}
Best Practices
-
Tenant Isolation
- Maintain strict data separation
- Validate tenant context
- Handle cross-tenant operations carefully
-
Performance
- Cache tenant information
- Optimize tenant resolution
- Minimize tenant-specific operations
-
Security
- Validate tenant access
- Implement proper authorization
- Secure tenant-specific data
Environment Configuration
Required environment variables:
NEXT_PUBLIC_API_URL
: API endpoint for tenant operationsNEXT_PUBLIC_APP_URL
: Application base URL