Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Tenancy Laravel Package

tomatophp/filament-tenancy

Filament Tenancy by TomatoPHP adds multi-tenancy to Filament panels: switch tenants, scope resources and queries per tenant, and manage tenant records with straightforward configuration for Laravel apps.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a Filament UI layer over stancl/tenancy — tenant/member management resources, tenant-aware panels, resource scoping, domain or path resolution. It is not a tenancy engine, and adopting it does not commit us to a novel isolation model; it commits us to stancl/tenancy's database-per-tenant model plus a thin admin surface. That is the right framing for a build-vs-buy call: the underlying architecture is already the industry default, and what we're actually evaluating is whether someone else's admin plumbing saves us a sprint. If we're already on Filament, fit is strong. If we're not, this package is not a reason to adopt Filament.

Integration feasibility. High for a timeboxed spike. The install path is conventional (composer require, publish config and migrations, migrate the central connection, register the plugin on the tenant panel). The real work is not installation but two configuration files — config/tenancy.php (connections, tenancy_db_name resolution, bootstrappers, seeder_parameters) and config/filament-tenancy.php (tenant model, routing, UI behaviour) — plus splitting migrations into central and tenant directories. The v5 release specifically reduced integration risk by moving owner creation inside $tenant->run() so it works across all database drivers, preserving the operator-supplied Unique ID as the tenant id, and decoupling tenant seeding from the application DatabaseSeeder. Those three fixes remove the most common failure modes from the creation flow.

Technical risk. Code risk is low; lifecycle risk is moderate-to-high. The package has 62 stars and zero dependents, which means we are effectively the QA function for anything beyond the happy path. It ships breaking changes on a real cadence (v4→v5 changed the owner-write flow and the plugin class name), and version lines are managed as branches (v3 is a branch switch, not a composer constraint) — a governance detail that will bite anyone assuming semver. Separate from the package, the model carries inherent operational risk: cache, session, and file storage isolation are not solved here; Octane and long-lived queue workers require explicit tenancy()->end() plus connection purge; config:cache freezes a placeholder tenant connection; and the tenant id is whatever an operator typed, which becomes a database name and URL segment.

Key questions.

  • Do we need database-per-tenant for contractual, procurement, or compliance reasons — or is row-level scoping sufficient? If we can't name the requirement, we're buying infrastructure we don't need.
  • What is our authentication model: per-tenant user tables, or central users with a tenant pivot? v5 writing owners through the tenant connection makes this a decision, not a default, and it's the top source of "the owner exists but I can't log in."
  • Who owns the tenant ID format? It becomes the database name, the route slug, and the FK target. Do we constrain it at the form, or accept operator input and validate downstream?
  • Are we on Filament 5 / Livewire 4 / Laravel 12–13 / PHP 8.2+? If we're mid-upgrade, do we land the panel upgrade and tenancy together?
  • What is our exit cost if the maintainer goes dark? Can we fork and maintain a ~thin UI layer, or does the stancl/tenancy dependency dominate?
  • Is there a commercial isolation tier in the roadmap that this would underpin, and does the unit economics case survive contact with per-tenant provisioning and backup costs?

Integration Approach

Stack fit. Treat the version matrix as a hard gate, not a preference: Filament 5, Livewire 4, Laravel 12 or 13, PHP 8.2+, stancl/tenancy 3.9+. Pin both tomatophp/filament-tenancy and stancl/tenancy to exact versions in composer.json. On Filament 3, we install from the v3 branch and accept that we are on a maintenance line, not the mainline.

Migration path. From a single shared, row-scoped database, the credible path is incremental: pilot one panel, one tenant, end to end, then expand. No big-bang rewrite. The vertical slice to prove is: central admin creates a tenant → provisioning creates the database and runs tenant migrations → $tenant->run() writes the owner → visiting the tenant route initialises the tenant → queries hit the tenant database. If that loop works with one tenant, everything else is elaboration. If it doesn't, we've spent days, not a quarter, finding out.

Compatibility. Two contracts run in parallel and must not be conflated. Filament's native tenancy (getTenants() / HasTenants) is relationship-based and must resolve on the central connection, while the panel's actual data queries resolve on the tenant connection. The package doesn't reconcile those for us. Likewise, it doesn't provide per-tenant cache prefixes, session isolation, or storage roots — those are ours to configure at storage/app/tenants/{id} and in the bootstrappers. Any v4 isolation gap carries straight into v5.

Sequencing.

  1. Spike branch: install, publish config, migrate central, stand up one tenant panel.
  2. Prove the vertical slice with a single tenant on path-based routing (/app/{tenant}) locally.
  3. Write two tests before anything else: one asserting the isolation boundary in both directions (tenant connection sees tenant data, central connection still sees central data), one asserting owner writes land in the tenant database. That pair catches most upgrade regressions.
  4. Wrap provisioning, switching, and seeding in our own TenantManager action class — one place to patch when v6 shifts the flow again.
  5. Add fleet tooling: our own tenants:migrate wrapper that logs per-tenant failures and continues rather than aborting mid-rollout, and deletion hooks that drop the database, domain rows, and files.
  6. Only then: self-serve registration, tenant switcher, and domain-based resolution in a production-like environment.

Operational Impact

Maintenance. We own it. Budget for reading release notes before every bump, and assume the seam between "package" and "our code" needs to be a single class we control. The Tenant model is meant to be extended (plan, status, trial columns — never the id), and $tenant->run() plus the stancl bootstrappers are the sanctioned extension points. Anything we build outside those points will cost us on upgrade.

Support. No vendor, no SLA, single-maintainer bus factor, MIT license. The realistic answer to "who fixes this at 2am" is us. That is acceptable for admin-surface plumbing and unacceptable if we let it become load-bearing on a revenue-critical path without a fork plan.

Scaling. Database-per-tenant shifts cost from query complexity to per-tenant operations: provisioning latency at signup, migration runtime that grows linearly with the fleet, per-tenant backup and point-in-time recovery, per-tenant deletion on churn, and open-connection/file-descriptor pressure per worker. These are the numbers we need before quoting an isolation tier — and the reason to pilot rather than estimate.

Failure modes to design against.

  • Silent empty tenant. Seeding is opt-in via tenancy.seeder_parameters.--class. Unset means creation succeeds with an empty database and no error — a guaranteed ticket generator.
  • Wrong-connection writes. The dominant failure class. Owner-creation and any tenant-scoped job must run inside $tenant->run() or explicitly initialise tenancy; queues must carry the tenant id in the payload because long-lived workers stay on the previous tenant's connection.
  • Cross-tenant leakage in shared workers. Octane and queue workers need RequestTerminated / JobProcessed cleanup calling tenancy()->end() and DB::purge(). If we can't guarantee that, we don't put Octane in front of tenant panels.
  • Cached-config placeholder. Any code reading the tenant database before initialisation gets a config-cached placeholder. Never trust a cached database value.
  • Immutable ID, retrofitted too late. The Unique ID is the tenant id, the route segment, and the database name. Make it read-only post-creation or write an explicit rename command that renames the DB and purges stale connections.
  • Orphaned resources. Deleting a tenant without hooks leaves databases, domain rows, and files behind.
  • Route collisions. v5's register component redirects to the package's own tenancy.* routes; a custom catch-all breaks it silently.

Ramp-up. Roughly one engineer-day to a working single-tenant vertical slice, plus two to three days to harden provisioning, queue handling, deletion, and fleet migrations behind a TenantManager. The steeper cost is conceptual, not technical: the team must internalise that the tenant id is immutable and operator-supplied, that tenant rows have no database column (it lives in the data JSON as tenancy_db_name), that seeding is opt-in, and that auth resolution and data resolution happen on different connections. Write the debugging checklist into the runbook — tenant initialised?, id matches URL?, tenant connection actually reached the PDO?, default connection vs. model connection agree?, seeder class set?, middleware ordered before panel boot? — and the on-call load drops sharply.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle