Aplicações SaaS modernas geralmente precisam atender múltiplos clientes utilizando a mesma infraestrutura. Esse modelo é conhecido como multi-tenant architecture — onde diferentes organizações (tenants) compartilham o mesmo sistema, mas com seus dados completamente isolados. Neste artigo, apresento como estruturar esse padrão utilizando PostgreSQL, com foco em simplicidade, escalabilidade e segurança.
O que é uma arquitetura multi-tenant
Em uma aplicação multi-tenant, vários clientes utilizam a mesma aplicação e banco de dados, mas cada cliente possui seus próprios dados isolados. O sistema precisa garantir que usuários de uma empresa nunca tenham acesso às informações de outra. Esse modelo é amplamente utilizado em produtos SaaS como plataformas de gestão, CRMs, marketplaces e sistemas corporativos.
Principais estratégias de multi-tenancy
Existem três abordagens comuns para implementar multi-tenancy em bancos de dados:
- Database per tenant: cada cliente possui um banco de dados separado.
- Schema per tenant: cada cliente possui um schema próprio dentro do mesmo banco.
- Shared database com tenant_id: todos os dados ficam no mesmo banco e tabelas, mas cada registro possui um identificador de tenant.
Na maioria dos produtos SaaS modernos, a abordagem mais utilizada é a terceira: shared database com tenant_id. Ela oferece o melhor equilíbrio entre escalabilidade, simplicidade operacional e custo de infraestrutura.
Modelagem do banco de dados
O princípio básico é simples: praticamente todas as tabelas relacionadas a dados de negócio devem possuir uma coluna tenant_id. Esse campo identifica a qual organização aquele dado pertence.
CREATE TABLE tenants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id),
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id),
total NUMERIC NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);Esse padrão garante que todos os dados estejam vinculados a um tenant específico. A partir disso, todas as consultas devem sempre filtrar pelo tenant_id.
SELECT * FROM orders
WHERE tenant_id = 'tenant-uuid';Aplicando isolamento no backend
No backend da aplicação, o tenant_id normalmente é identificado a partir do usuário autenticado. Isso significa que todas as queries executadas pelo sistema devem automaticamente aplicar esse filtro.
const orders = await db.orders.findMany({
where: {
tenantId: session.tenantId
}
});Esse padrão impede que usuários acessem dados de outras organizações e mantém o sistema consistente.
Row Level Security no PostgreSQL
Uma camada adicional de segurança pode ser implementada usando Row Level Security (RLS) do PostgreSQL. Com RLS, o próprio banco garante que apenas registros do tenant correto possam ser acessados.
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_policy
ON orders
USING (tenant_id = current_setting('app.current_tenant')::uuid);Com essa abordagem, mesmo que uma query seja executada sem o filtro adequado no backend, o banco ainda protegerá o acesso aos dados.
Escalabilidade em sistemas multi-tenant
A arquitetura baseada em tenant_id também facilita escalar o sistema. Algumas estratégias comuns incluem:
- Indexação por tenant_id para melhorar performance de consultas.
- Particionamento de tabelas baseado em tenant_id.
- Separação de tenants maiores em bancos dedicados conforme o crescimento da plataforma.
- Uso de caches por tenant para reduzir carga no banco.
Aplicações reais em produtos SaaS
Esse padrão é utilizado em diversos tipos de produtos SaaS, como plataformas de gestão empresarial, sistemas de agendamento, marketplaces e CRMs. Em projetos que desenvolvi recentemente, a arquitetura multi-tenant permitiu atender múltiplos clientes mantendo isolamento de dados e reduzindo custos operacionais.
Conclusão
Arquiteturas multi-tenant são a base de muitos produtos SaaS modernos. Utilizando PostgreSQL e um design consistente baseado em tenant_id, é possível construir sistemas escaláveis, seguros e relativamente simples de manter. Quando combinada com boas práticas de backend e segurança no banco, essa abordagem se torna uma solução robusta para plataformas multi-cliente.
