A tenant is a SaaS customer: a company, a team or a shop. Multitenancy means one application and codebase that serves many tenants while each sees only its own data.
Three approaches
| Topic | Single database | Database per tenant |
|---|---|---|
| Isolation | logical (scope) | physical |
| Migrations | once | for every tenant |
| Many tenants | easy | database count grows |
| Backup | all together | per tenant |
| Reports | simple | cross-tenant is hard |
💡 Start with one database and
tenant_id. Move to a database per tenant only when a contract, a regulation or a very large customer demands it.
Single database: tenant_id and a global scope
Keep the resolved tenant in one small object. Register it as scoped, so it is reset for every request and queue job.
namespace App\Support;
use App\Models\Tenant;
use RuntimeException;
final class CurrentTenant
{
private ?Tenant $tenant = null;
public function set(Tenant $tenant): void
{
$this->tenant = $tenant;
}
public function id(): int
{
return $this->tenant?->id
?? throw new RuntimeException('No tenant resolved');
}
}
// AppServiceProvider::register()
$this->app->scoped(CurrentTenant::class);namespace App\Models\Scopes;
use App\Support\CurrentTenant;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class TenantScope implements Scope
{
public function apply(Builder $builder, Model $model): void
{
$builder->where(
$model->getTable().'.tenant_id',
app(CurrentTenant::class)->id(),
);
}
}namespace App\Models\Concerns;