Multitenancy no Laravel com Spatie e Sanctum (Database por Tenant)
Visão Geral
Implementar multitenancy por banco de dados é a forma mais segura de isolar dados em aplicações SaaS. Neste guia, você verá uma abordagem prática usando Laravel, Spatie Multitenancy e Sanctum, com foco em clareza, organização e boas práticas de produção.
O que é multitenancy?
Multitenancy é uma arquitetura onde uma única aplicação atende múltiplos clientes (tenants), mantendo isolamento entre seus dados.
Principais abordagens:
- Row-based - todos os dados na mesma tabela (coluna
tenant_id) - Schema-based - schemas separados no mesmo banco
- Database-based (recomendado) - um banco por tenant
*Este artigo utiliza database por tenant, garantindo isolamento total.
Arquitetura geral
- Landlord (banco principal)
Armazena tenants, domínios e metadados - Tenant (bancos isolados)
Cada cliente possui seu próprio banco - TenantFinder
Resolve o tenant via domínio/subdomínio - Tasks
Trocam dinamicamente a conexão ativa - Autenticação (Sanctum)
Gerencia autenticação por tenant
Passo 1 - Instalação e configuração
Instale o pacote:
1
composer require spatie/laravel-multitenancy
Configure duas conexões no config/database.php:
1
2
3
4
5
6
7
8
'connections' => [
'landlord' => [
// conexão principal
],
'tenant' => [
// conexão dinâmica
],
]
Passo 2 - Separação de migrations
Organize suas migrations:
1
2
database/migrations/landlord
database/migrations/tenant
- Landlord → tabela de tenants
- Tenant → tabelas da aplicação
Isso evita mistura de contexto e facilita manutenção.
Passo 3 - Model Tenant
1
2
3
4
5
6
7
8
9
10
class Tenant extends Model
{
protected $connection = 'landlord';
protected $fillable = [
'id',
'database',
'domain',
];
}
Passo 4 - Resolver o tenant (TenantFinder)
1
2
3
4
5
6
7
class DomainTenantFinder extends TenantFinder
{
public function findForRequest(Request $request): ?Tenant
{
return Tenant::where('domain', $request->getHost())->first();
}
}
Passo 5 - Troca dinâmica de conexão
1
SwitchTenantDatabaseTask::class
Essa task altera automaticamente a conexão tenant para o banco correto.
Passo 6 - Autenticação com Sanctum
- Tokens devem ser isolados por tenant
- Evite compartilhar sessão entre tenants
1
2
3
4
5
6
use Laravel\Sanctum\PersonalAccessToken as SanctumToken;
class PersonalAccessToken extends SanctumToken
{
protected $connection = 'tenant';
}
Passo 7 - Criação de tenants
1
php artisan tenant:create
Fluxo típico:
- Criar registro no landlord
- Criar banco do tenant
- Executar migrations do tenant
Isolamento de dados
Com database por tenant:
-
Não há compartilhamento de dados
-
Reduz risco de vazamento
-
Ideal para aplicações SaaS multiempresa
Erros comuns
Misturar landlord e tenant
- Queries no banco errado
- Models sem
connectiondefinida
Cache sem isolamento
- Use prefixo por tenant
Jobs sem contexto
- Executam no banco errado
Boas práticas
✔ Cache por tenant
1
PrefixCacheTask::class
Jobs tenant-aware
- Sempre propagar o contexto do tenant
Seed por tenant
- Cada banco deve ter seus próprios dados iniciais
Logs com identificação
- Inclua
tenant_idnos logs
Resumo da arquitetura
- Tenant → banco isolado
- Resolver → identifica o tenant
- Tasks → trocam conexão
- Autenticação → isolada por tenant
Conclusão
Multitenancy bem implementado garante:
- Segurança
- Escalabilidade
- Organização arquitetural
Essa abordagem é ideal para sistemas SaaS que exigem isolamento forte de dados.
