Multi-tenancy em SaaS: a arquitetura que não engasga quando você escala
Guia técnico prático sobre multi-tenancy: os três modelos, quando usar cada um, e como evitar os erros que causam vazamento de dados entre clientes
Alienhub Team
Product Engineering
Multi-tenancy é uma das decisões arquiteturais mais importantes de um SaaS — e também uma das mais ignoradas em early-stage.
Você constrói com um único cliente em mente, chega a 50, e descobre que a arquitetura não suporta isolamento de dados, customização por cliente ou a performance que prometeu.
A boa notícia: você não precisa de arquitetura perfeita desde o dia 1. Precisa de arquitetura que não te prenda em refactor doloroso quando crescer.
O que é multi-tenancy
Multi-tenancy significa que sua aplicação serve múltiplos clientes (tenants) compartilhando a mesma infraestrutura — mas com dados completamente isolados entre eles.
O usuário da Empresa A não pode ver dados da Empresa B. Operação da Empresa A não pode afetar performance da Empresa B. Empresa A pode ter customizações que Empresa B não tem.
Isso soa óbvio, mas a implementação errada causa o maior pesadelo de SaaS: vazamento de dados entre tenants. Um bug que expõe dados de clientes pode destruir reputação e violar LGPD/GDPR.
Os três modelos de multi-tenancy
Modelo 1: Banco de dados por tenant (Database per Tenant)
Cada cliente tem seu próprio banco de dados.
Empresa A → banco_empresa_a
Empresa B → banco_empresa_b
Empresa C → banco_empresa_c
Vantagens:
- Isolamento máximo: impossível vazar entre tenants
- Backup/restore por cliente independente
- Compliance mais simples (dados de cliente na UE? Banco na UE)
- Customização de schema por cliente se necessário
Desvantagens:
- Custo de infra sobe linearmente com clientes
- Migrations são executadas N vezes (um por banco)
- Cross-tenant analytics é complexo
- Operacionar 500 bancos de dados é caro e trabalhoso
Quando usar:
- Enterprise com exigências rígidas de compliance e isolamento
- Ticket médio alto (> R$ 5.000/mês) que justifica o custo
- Clientes que exigem LGPD/GDPR com dados em região específica
Modelo 2: Schema por tenant (Schema per Tenant)
Um banco de dados, mas cada cliente tem seu próprio schema.
-- Empresa A
empresa_a.users
empresa_a.orders
empresa_a.products
-- Empresa B
empresa_b.users
empresa_b.orders
empresa_b.products
Disponível nativamente no PostgreSQL.
Vantagens:
- Isolamento forte sem custo de múltiplos bancos
- Migrations possíveis em paralelo por schema
- Cada tenant pode ter extensions ou configurações diferentes
- Backup por tenant ainda possível
Desvantagens:
- Escalabilidade limitada: PostgreSQL aguenta ~1.000 schemas bem, depois degrada
- Connection pool por schema é complicado (Pgpool, PgBouncer necessários)
- Cross-tenant queries são trabalhosas
- Operacional ainda complexo para muitos tenants
Quando usar:
- SaaS com poucos clientes (< 500) que precisam de isolamento forte
- Quando compliance exige isolamento mas não exige bancos separados
- Produto B2B mid-market
Modelo 3: Shared schema com tenant_id (Shared Everything)
Um banco, um schema, uma coluna tenant_id em todas as tabelas.
CREATE TABLE orders (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL REFERENCES tenants(id),
-- campos do pedido
created_at TIMESTAMP
);
-- Index obrigatório
CREATE INDEX idx_orders_tenant ON orders(tenant_id);
Toda query filtra por tenant_id:
SELECT * FROM orders WHERE tenant_id = $current_tenant AND ...;
Vantagens:
- Custo de infra mínimo (um banco pra tudo)
- Migrations simples (um schema)
- Cross-tenant analytics trivial
- Escala para milhares de tenants sem mudança de arquitetura
Desvantagens:
- Risco real de vazamento: bug que não filtra
tenant_idexpõe dados de todos - Compliance mais complexo (dados misturados no mesmo banco)
- Performance compartilhada: tenant que usa muito afeta outros
- Menos customização por tenant
Quando usar:
- SaaS com muitos tenants (B2C, SMB, PLG)
- Early-stage onde custo de infra importa
- Ticket médio baixo-médio
Multi-tenancy na prática: o modelo compartilhado com segurança
Para a maioria dos SaaS em early-stage, o modelo shared schema é o caminho. Mas exige implementação cuidadosa para não vazar dados.
Row Level Security (RLS) no PostgreSQL
O jeito mais robusto de garantir isolamento no banco: deixe o banco aplicar o filtro, não o código.
-- Ativa RLS na tabela
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- Política: usuário só vê registros do próprio tenant
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.tenant_id')::UUID);
No seu application code, antes de qualquer query:
SET app.tenant_id = '550e8400-e29b-41d4-a716-446655440000';
Agora é fisicamente impossível para o banco retornar dados de outro tenant, mesmo que o código esqueça o filtro.
Implementação em Node.js/TypeScript com Prisma:
async function withTenant<T>(
tenantId: string,
fn: (tx: PrismaClient) => Promise<T>
): Promise<T> {
return prisma.$transaction(async (tx) => {
await tx.$executeRaw`SET app.tenant_id = ${tenantId}`;
return fn(tx);
});
}
// Uso
const orders = await withTenant(req.user.tenantId, (tx) =>
tx.order.findMany()
);
Middleware de tenant em aplicações web
Toda request precisa resolver o tenant antes de qualquer lógica de negócio.
Como identificar o tenant:
- Subdomínio:
empresa-a.seuapp.com→ resolve para tenantempresa-a - Header:
X-Tenant-ID: uuid(para APIs B2B) - JWT claim: token contém
tenant_idno payload - Path:
/orgs/empresa-a/dashboard
// Middleware Express
async function resolveTenant(req, res, next) {
const subdomain = req.hostname.split('.')[0];
const tenant = await db.tenant.findUnique({
where: { subdomain }
});
if (!tenant) return res.status(404).json({ error: 'Tenant not found' });
req.tenant = tenant;
next();
}
Indexes obrigatórios
Sem index em tenant_id, suas queries fazem full table scan. Com 1 million rows e 1.000 tenants, isso é catástrofe de performance.
-- Index composto: tenant + campo mais filtrado
CREATE INDEX idx_orders_tenant_status
ON orders(tenant_id, status);
CREATE INDEX idx_users_tenant_email
ON users(tenant_id, email);
Regra: toda tabela com tenant_id deve ter index composto (tenant_id, campo_mais_buscado).
Erros comuns (e como evitar)
Erro 1: Esquecer tenant_id em uma tabela
Você tem 30 tabelas. Uma não tem tenant_id porque parece "global". Seis meses depois, descobre que dados de um tenant afetam outro.
Solução: auditoria de schema. Todo model precisa de tenant_id ou uma justificativa clara de porque não precisa (tabelas realmente globais: countries, currencies, planos de assinatura).
Erro 2: Queries sem filtro de tenant
Desenvolvedor novo escreve:
SELECT * FROM users WHERE email = $1
Sem tenant_id. Isso retorna usuários de todos os tenants com aquele email.
Solução: RLS no banco (descrito acima) + code review checklist que inclui "todas as queries filtram por tenant?"
Erro 3: Tenant isolation só em produção
Em desenvolvimento, todos usam o mesmo tenant. Bug de isolamento não é detectado até produção.
Solução: em ambiente de desenvolvimento, cria múltiplos tenants de teste. Testa troca de tenant ativamente.
Erro 4: Logs sem tenant_id
Quando dá bug, você não sabe qual cliente foi afetado.
Solução: structured logging sempre inclui tenant_id:
logger.info('Order created', {
tenantId: req.tenant.id,
orderId: order.id,
userId: req.user.id
});
Erro 5: Background jobs sem tenant context
Job que roda em background e processa dados "de todos os tenants" pode vazar se não tiver isolamento explícito.
Solução: todo job recebe tenantId como parâmetro e aplica filtro.
Migrando de single-tenant para multi-tenant
Se você já tem produto single-tenant e precisa migrar:
- Adiciona tabela
tenantscom as configs globais do tenant - Cria tenant padrão com os dados atuais
- Adiciona
tenant_idem todas as tabelas (nullable inicialmente) - Popula
tenant_idem todos os registros com o tenant padrão - Aplica NOT NULL na coluna após população
- Ativa RLS
- Atualiza toda a application layer para passar
tenant_id
Esse processo é trabalhoso mas seguro se feito com feature flags e migração gradual.
A gente na Alienhub tem experiência em arquitetar e migrar SaaS para multi-tenancy de forma segura. Se você tá crescendo e precisa estruturar isso antes de ser problema, bora bater um papo.
Construindo seu SaaS?
Receba insights semanais sobre produto, tecnologia e negócios para fundadores de SaaS e Micro-SaaS.
Continue Lendo

