Multi-Tenant Kit
Available in: Enterprise tier
Zod helpers to validate tenant context at API/UI boundaries for SaaS applications.
Why Use Multi-Tenant Kit
Problem: Multi-tenant applications need strict data isolation:
- Tenant data must never leak across tenants
- Every request needs tenant validation
- UI needs tenant-aware components
- Manual tenant checks are error-prone
Solution: Generate Zod helpers that enforce tenant context validation at every API and UI boundary.
Benefits
- Strict Isolation: Validate tenant access before data operations
- Type-Safe: Full TypeScript validation
- Configurable Modes: Strict, warn, or log violations
- UI Integration: React context provider for tenant state
Prerequisites
# Core dependencies
pnpm add zod react @prisma/client
# PZG Pro license required
Generate
Add to your schema.prisma:
generator pzgPro {
provider = "node ./node_modules/prisma-zod-generator/lib/cli/pzg-pro.js"
output = "./generated/pro"
enableMultiTenant = true
}
Then run:
prisma generate
Generated Files
generated/
pro/
multi-tenant/
schemas/
tenant-schemas.ts # Tenant-aware Zod schemas
middleware/
prisma-middleware.ts # Prisma middleware for tenant filtering
extensions/
prisma-extension.ts # Prisma client extensions
utils/
validation.ts # Validation utilities
context.ts # Tenant context helpers
types/
tenant-types.ts # TypeScript types
README.md # Usage documentation
Basic Usage
import { validateTenantAccess } from '@/generated/pro/multi-tenant/utils/validation'
// Modes: 'strict' | 'warn' | 'log'
const isValid = validateTenantAccess(
{ tenantId: 't1' }, // Request context
't1', // Expected tenant
'strict' // Mode
)
if (!isValid) {
throw new Error('Tenant mismatch')
}
Validation Modes
- strict: Throws error on mismatch
- warn: Logs warning but continues
- log: Logs info for debugging
UI Pattern
Provide a TenantProvider with the current tenant and refine schemas based on it:
// Example tenant provider pattern
import { TenantProvider } from '@/generated/pro/multi-tenant/schemas/tenant-schemas'
export default function App() {
const tenant = getCurrentTenant() // From auth/session
return (
<TenantProvider value={{ tenantId: tenant.id }}>
<YourApp />
</TenantProvider>
)
}
See generated comments in the file for more integration patterns.
See Also
- PostgreSQL RLS - Database-level tenant isolation
- Policies & Redaction - Field-level access control