5.1 KiB
5.1 KiB
| title | aliases | tags | sources | created | updated | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Multi-Tenant Plugin |
|
|
|
2026-05-15 | 2026-05-15 |
Overview
@payloadcms/plugin-multi-tenant scaffolds full multi-tenancy inside a single Payload instance. It adds a tenant relationship field to every specified collection, injects a tenant selector into the Admin Panel, and filters list views + relationship pickers to the active tenant.
Core Features
- Adds
tenantfield to each opted-in collection - Admin Panel tenant selector — switches context, filters all list views
- Filters relationship fields by active tenant
- Global-like collections —
isGlobal: trueenforces 1 doc per tenant - Auto-assigns tenant to new documents
- Cleans up documents when a tenant is deleted (
cleanupAfterTenantDelete, defaulttrue)
Warning: Tenant deletion cascades to all related documents by default. Apply strong access control on the tenants collection or set
cleanupAfterTenantDelete: false.
Installation
pnpm add @payloadcms/plugin-multi-tenant
Basic Config
import { multiTenantPlugin } from '@payloadcms/plugin-multi-tenant'
import type { Config } from './payload-types'
export default buildConfig({
collections: [
{
slug: 'tenants',
admin: { useAsTitle: 'name' },
fields: [
{ name: 'name', type: 'text', required: true },
{ name: 'slug', type: 'text', required: true },
{ name: 'domain', type: 'text', required: true },
],
},
],
plugins: [
multiTenantPlugin<Config>({
collections: {
pages: {},
navigation: { isGlobal: true }, // 1 doc per tenant
},
}),
],
})
You own the tenants collection — add any fields you need (slug, domain, plan, etc.).
Key Options
| Option | Default | Purpose |
|---|---|---|
collections |
required | Map of collection slugs to per-collection options |
tenantsSlug |
'tenants' |
Slug for the tenants collection |
cleanupAfterTenantDelete |
true |
Remove tenant's docs on deletion |
userHasAccessToAllTenants |
— | Function for super-admin bypass |
tenantsArrayField.includeDefaultField |
true |
Auto-add tenants array to users |
useBaseFilter |
true |
Filter list view + relationships by tenant |
useTenantAccess |
true |
Apply access constraints per tenant |
debug |
false |
Show tenant field in Admin UI |
Per-Collection Options
collections: {
pages: {
isGlobal: false, // single doc per tenant?
useBaseFilter: true, // filter list + relationships
useTenantAccess: true, // enforce tenant access control
customTenantField: false, // manually place tenantField export
accessResultOverride: ..., // override access control result
}
}
Frontend Querying
Filter any enabled collection by tenant field:
const pages = await payload.find({
collection: 'pages',
where: {
'tenant.slug': { equals: 'gold' },
},
overrideAccess: false,
})
Next.js Domain-Based Rewrites
Route per domain to the matching tenant:
async rewrites() {
return [{
source: '/((?!admin|api)):path*',
destination: '/:tenantDomain/:path*',
has: [{ type: 'host', value: '(?<tenantDomain>.*)' }],
}]
}
useTenantSelection Hook
Access current tenant context in custom Admin components:
import { useTenantSelection } from '@payloadcms/plugin-multi-tenant/client'
const { selectedTenantID, setTenant, options } = useTenantSelection()
setTenant({ id: 'abc123', refresh: true })
Super-Admin Bypass
multiTenantPlugin<Config>({
collections: { pages: {} },
userHasAccessToAllTenants: (user) => user.roles?.includes('super-admin'),
})
Key Takeaways
- You own the tenants collection — plugin just references it; define your own fields (slug, domain, plan, etc.)
isGlobal: trueenforces exactly one document per tenant (navigation, settings, etc.)- Cascade delete is on by default — guard the tenants collection or disable with
cleanupAfterTenantDelete: false useBaseFilterfilters both the list view AND relationship pickers — setting tofalserequires manual filteringuserHasAccessToAllTenantsis the correct hook for super-admin users, not disablinguseTenantAccessuseTenantSelectionhook lets custom Admin components read/set the active tenant- Domain routing: combine with Next.js rewrites to map domains → tenant slugs automatically
Related
- wiki/payloadcms/plugins — all 10 official plugins overview
- wiki/payloadcms/access-control — how access control integrates with tenant isolation
- wiki/payloadcms/collection-config — collection-level options used by the plugin
- wiki/payloadcms/authentication-overview — user collection that gets the tenants array field
Sources
raw/plugins__multi-tenant.md- https://payloadcms.com/docs/plugins/multi-tenant