Stancl Tenancy v3 — Multi-Tenant Laravel
Comprehensive agent skill for building multi-tenant SaaS applications with stancl/tenancy v3 (^3.9). Covers the full package API surface, real-world production patterns, and critical gotchas.
What this skill covers
- Package architecture — central vs tenant contexts, automatic/manual tenancy modes, tenant model patterns
- Tenant identification —
InitializeTenancyByDomain, InitializeTenancyBySubdomain, InitializeTenancyByPath, InitializeTenancyByRequestData middleware with custom $onFail handling
- Data isolation — multi-database (per-tenant databases) and single-database (
BelongsToTenant, BelongsToPrimaryModel, HasScopedValidationRules, unique index scoping, withoutTenancy())
- Bootstrappers — database, cache, filesystem, queue, Redis bootstrappers + patterns for custom bootstrappers
- Features —
TenantConfig (per-tenant Laravel config), UserImpersonation, TelescopeTags, UniversalRoutes
- Event system — full lifecycle events with
JobPipeline for sequential job execution
- Console commands —
tenants:migrate, tenants:seed, tenants:rollback, tenants:list, tenants:run with --tenants=<id> filtering
- Production patterns — queue isolation strategies (tenant-specific queues, priority queues, dedicated workers), idempotent provisioning, deployment-scale migrations, Horizon job tagging, Scout Meilisearch index scoping, Spatie package integration, Livewire tenant routing
- Testing — fast transaction-based testing (25x speed improvement),
Event::fake() caveats, event faking for isolation
- Critical gotchas — queued events +
SerializesModels trap (never pass tenant-scoped models), DatabaseBatchRepository stale connection fix, bootstrapper prefix accumulation in long-running processes
Common patterns
// Tenant model with domains and databases
class Tenant extends BaseTenant implements TenantWithDatabase
{
use HasDatabase, HasDomains;
public function getCustomColumns(): array
{
return ['id', 'name', 'plan_id', 'status'];
}
}
// Event-driven tenant lifecycle
Event::listen(TenantCreated::class, JobPipeline::make([
CreateDatabase::class,
MigrateDatabase::class,
SeedDatabase::class,
])->send(fn ($event) => $event->tenant)->toListener());
// Manual tenancy control
$tenant->run(fn () => User::create([...]));
tenancy()->initialize($tenant);
tenancy()->end();
// Custom bootstrapper
class ScoutTenancyBootstrapper implements TenancyBootstrapper
{
public function bootstrap(Tenant $tenant): void { /* scope Meilisearch */ }
public function revert(): void { /* restore central config */ }
}
// Single-database scoping
class Post extends Model { use BelongsToTenant; }
class Comment extends Model { use BelongsToPrimaryModel; }
Critical Gotchas
Queued events + SerializesModels: Never pass tenant-scoped models in queued payloads. BelongsToTenant's global scope fires before QueueTenancyBootstrapper restores context. Pass scalars (tenantId, modelId) and call tenancy()->initialize() in handle().
DatabaseBatchRepository: DB::purge('tenant') between jobs nulls the PDO. Use houlokmah/tenancy-batch-fix for batched jobs across tenants.
Prefix accumulation: Cache/Redis/filesystem bootstrappers can accumulate prefixes across tenant switches in long-running processes (Horizon, Octane). Always test after multiple cycles.
For full patterns including queue isolation strategies, transaction-based testing (25x speed), and provisioning safety, see references/production-patterns.md in the skill source.
Installation
OpenClaw
clawhub install tenancy-development
Direct repo/manual install
git clone https://github.com/Xyntax01/tenancy-development.git
cp -R tenancy-development ~/.claude/skills/tenancy-development
Optional Third-Party Installer
npm exec --package=skills@1.5.7 -- skills add agentskillexchange/skills --skill tenancy-development -a claude-code
Documentation Links
1---2name: stancl-tenancy-v3-multi-tenant-laravel3description: Builds multi-tenant Laravel SaaS applications with stancl/tenancy v3, covering tenant identification, data isolation, bootstrappers, queues, and production patterns.4---56# Stancl Tenancy v3 — Multi-Tenant Laravel78Comprehensive agent skill for building multi-tenant SaaS applications with [stancl/tenancy](https://tenancyforlaravel.com) v3 (`^3.9`). Covers the full package API surface, real-world production patterns, and critical gotchas.910## What this skill covers1112- **Package architecture** — central vs tenant contexts, automatic/manual tenancy modes, tenant model patterns13- **Tenant identification** — `InitializeTenancyByDomain`, `InitializeTenancyBySubdomain`, `InitializeTenancyByPath`, `InitializeTenancyByRequestData` middleware with custom `$onFail` handling14- **Data isolation** — multi-database (per-tenant databases) and single-database (`BelongsToTenant`, `BelongsToPrimaryModel`, `HasScopedValidationRules`, unique index scoping, `withoutTenancy()`)15- **Bootstrappers** — database, cache, filesystem, queue, Redis bootstrappers + patterns for custom bootstrappers16- **Features** — `TenantConfig` (per-tenant Laravel config), `UserImpersonation`, `TelescopeTags`, `UniversalRoutes`17- **Event system** — full lifecycle events with `JobPipeline` for sequential job execution18- **Console commands** — `tenants:migrate`, `tenants:seed`, `tenants:rollback`, `tenants:list`, `tenants:run` with `--tenants=<id>` filtering19- **Production patterns** — queue isolation strategies (tenant-specific queues, priority queues, dedicated workers), idempotent provisioning, deployment-scale migrations, Horizon job tagging, Scout Meilisearch index scoping, Spatie package integration, Livewire tenant routing20- **Testing** — fast transaction-based testing (25x speed improvement), `Event::fake()` caveats, event faking for isolation21- **Critical gotchas** — queued events + `SerializesModels` trap (never pass tenant-scoped models), `DatabaseBatchRepository` stale connection fix, bootstrapper prefix accumulation in long-running processes2223## Common patterns2425```php26// Tenant model with domains and databases27class Tenant extends BaseTenant implements TenantWithDatabase28{29 use HasDatabase, HasDomains;3031 public function getCustomColumns(): array32 {33 return ['id', 'name', 'plan_id', 'status'];34 }35}3637// Event-driven tenant lifecycle38Event::listen(TenantCreated::class, JobPipeline::make([39 CreateDatabase::class,40 MigrateDatabase::class,41 SeedDatabase::class,42])->send(fn ($event) => $event->tenant)->toListener());4344// Manual tenancy control45$tenant->run(fn () => User::create([...]));46tenancy()->initialize($tenant);47tenancy()->end();4849// Custom bootstrapper50class ScoutTenancyBootstrapper implements TenancyBootstrapper51{52 public function bootstrap(Tenant $tenant): void { /* scope Meilisearch */ }53 public function revert(): void { /* restore central config */ }54}5556// Single-database scoping57class Post extends Model { use BelongsToTenant; }58class Comment extends Model { use BelongsToPrimaryModel; }59```6061## Critical Gotchas6263**Queued events + SerializesModels:** Never pass tenant-scoped models in queued payloads. `BelongsToTenant`'s global scope fires before `QueueTenancyBootstrapper` restores context. Pass scalars (`tenantId`, `modelId`) and call `tenancy()->initialize()` in `handle()`.6465**DatabaseBatchRepository:** `DB::purge('tenant')` between jobs nulls the PDO. Use `houlokmah/tenancy-batch-fix` for batched jobs across tenants.6667**Prefix accumulation:** Cache/Redis/filesystem bootstrappers can accumulate prefixes across tenant switches in long-running processes (Horizon, Octane). Always test after multiple cycles.6869For full patterns including queue isolation strategies, transaction-based testing (25x speed), and provisioning safety, see `references/production-patterns.md` in the skill source.7071## Installation7273### OpenClaw7475```bash76clawhub install tenancy-development77```7879### Direct repo/manual install8081```bash82git clone https://github.com/Xyntax01/tenancy-development.git83cp -R tenancy-development ~/.claude/skills/tenancy-development84```8586### Optional Third-Party Installer8788```bash89npm exec --package=skills@1.5.7 -- skills add agentskillexchange/skills --skill tenancy-development -a claude-code90```9192## Documentation Links9394- Official docs: https://tenancyforlaravel.com/docs/v3/95- Upstream repo: https://github.com/stancl/tenancy96- Skill source: https://github.com/Xyntax01/tenancy-development