Voltar para o inícioSaaS & Multi-tenancy

Como implementar isolamento por tenant em banco compartilhado: guia prático para produção

Aprenda a implementar isolamento por tenant em banco compartilhado com tenant_id, Row Level Security, controles na aplicação, testes de acesso cruzado e práticas de produção.

M

Max Alex

Como implementar isolamento por tenant em banco compartilhado: guia prático para produção

Em um SaaS, compartilhar a mesma infraestrutura de banco pode reduzir custos e simplificar a operação. Mas isso só funciona quando a separação entre clientes é tratada como uma fronteira de segurança verificável. Um filtro esquecido em uma consulta pode expor dados de outra organização.

Este guia mostra como implementar isolamento por tenant em banco compartilhado combinando modelagem, contexto autenticado, Row Level Security (RLS), testes e práticas operacionais para produção.

Entenda o modelo de banco compartilhado e seus limites

No modelo de banco compartilhado, vários tenants usam as mesmas tabelas e a maioria dos registros possui uma coluna tenant_id. Uma plataforma B2B pode, por exemplo, armazenar clientes, pedidos e usuários em estruturas comuns, sempre identificando a organização proprietária de cada dado.

Ele difere de schema por tenant, em que cada cliente recebe um schema separado, e de banco por tenant, em que cada cliente possui uma instância ou banco próprio. O compartilhamento costuma oferecer ganhos de custo, uso mais eficiente de recursos e menos componentes para administrar.

Esses ganhos não removem o principal risco: se a separação depender apenas de filtros escritos manualmente pela aplicação, uma consulta sem WHERE tenant_id = ... pode causar vazamento. Por isso, a arquitetura SaaS multi-tenant precisa prever controles em mais de uma camada.

O modelo é adequado quando os requisitos de segurança, residência de dados, contratos e regulações permitem infraestrutura compartilhada com controles robustos. Clientes com exigências de isolamento físico, chaves dedicadas ou limites operacionais muito específicos podem demandar uma estratégia híbrida ou dedicada.

Também considere o crescimento desde cedo. Uma boa estratégia de escalabilidade em SaaS deve incluir índices, limites de consumo e observabilidade para evitar que a carga de um tenant degrade a experiência dos demais.

Defina o tenant como uma fronteira de domínio e segurança

Antes de alterar tabelas, defina o que representa um tenant no produto. Pode ser uma empresa, uma organização, uma conta contratante ou uma unidade de negócio. A definição deve ser única e reconhecida por autenticação, autorização, banco, filas e ferramentas internas.

O tenant_id nunca deve ser aceito como um parâmetro livre enviado pelo navegador. Um usuário pode alterar esse valor antes de uma chamada. Em vez disso, a API deve validar a identidade autenticada, resolver a organização à qual ela tem acesso e montar um contexto de tenant confiável para a requisição.

Classifique as entidades do domínio. Planos públicos, catálogos globais e parâmetros de produto podem não pertencer a um tenant. Já usuários de clientes, documentos, pedidos, faturas e configurações normalmente pertencem. Essa classificação evita tanto a ausência indevida do escopo quanto a criação de colunas sem significado.

Administradores internos exigem cuidado adicional. Eles não devem receber implicitamente acesso irrestrito a todos os dados. Defina permissões, justificativas, auditoria e, quando necessário, fluxos explícitos de troca de contexto para acesso entre tenants.

Modele tabelas e relacionamentos com tenant_id obrigatório

Em tabelas que pertencem ao cliente, use tenant_id NOT NULL. A obrigatoriedade transforma uma convenção em regra estrutural: novos registros não podem existir sem proprietário definido.

Índices que começam por tenant_id tendem a atender bem consultas do dia a dia, pois a maior parte dos acessos já ocorre dentro de um tenant. O desenho exato depende dos filtros e ordenações reais da aplicação, mas o escopo deve participar da análise de desempenho.

Para regras únicas por organização, prefira restrições compostas. Um número de pedido pode se repetir entre clientes, mas não dentro do mesmo cliente:

CREATE TABLE pedidos (
  id uuid PRIMARY KEY,
  tenant_id uuid NOT NULL REFERENCES tenants(id),
  numero_pedido text NOT NULL,
  criado_em timestamptz NOT NULL DEFAULT now(),
  UNIQUE (tenant_id, numero_pedido)
);

CREATE INDEX pedidos_tenant_criado_em_idx
  ON pedidos (tenant_id, criado_em DESC);

Relacionamentos também precisam preservar o escopo. Em vez de permitir que um item referencie somente o identificador de um pedido, use chaves compostas ou uma restrição equivalente que associe tenant_id e pedido. Assim, um registro do Tenant A não consegue apontar para um pedido do Tenant B por acidente ou manipulação.

Para ajustar desempenho sem perder isolamento, avalie índices para consultas críticas a partir dos padrões medidos em produção. Não crie índices apenas por hábito: cada um tem custo de armazenamento e escrita.

Aplique Row Level Security como defesa no banco de dados

Filtros na aplicação continuam importantes, mas não devem ser a última barreira. No PostgreSQL, o Row Level Security permite associar políticas às tabelas para que o próprio banco controle quais linhas uma conexão pode ler ou alterar.

O padrão é definir o tenant atual no início de cada transação e fazer a política comparar esse valor com a coluna da linha. Uma configuração local à transação reduz o risco de contexto residual em conexões reutilizadas por pools.

ALTER TABLE pedidos ENABLE ROW LEVEL SECURITY;
ALTER TABLE pedidos FORCE ROW LEVEL SECURITY;

CREATE POLICY pedidos_por_tenant ON pedidos
  USING (tenant_id = current_setting('app.current_tenant', true)::uuid)
  WITH CHECK (tenant_id = current_setting('app.current_tenant', true)::uuid);

BEGIN;
SELECT set_config('app.current_tenant', 'UUID_DO_TENANT', true);
SELECT * FROM pedidos;
COMMIT;

A cláusula USING protege leituras, atualizações e exclusões; WITH CHECK valida inserções e os valores finais de atualizações. Ainda assim, revise o comportamento para tabelas relacionadas, views, funções, tarefas administrativas e papéis que possam ignorar RLS.

Usuários usados pela aplicação devem ter privilégios mínimos e não devem ser proprietários das tabelas sem uma decisão consciente. Rotinas de manutenção e suporte precisam usar credenciais separadas, permissões restritas e trilhas de auditoria. Esse desenho faz parte de uma estratégia mais ampla de segurança no banco de dados e na aplicação.

RLS é defesa em profundidade, não substituto para autorização de negócio. Uma política pode confirmar que a linha pertence ao tenant atual, enquanto a aplicação decide se aquele usuário pode aprovar um pedido, exportar um relatório ou administrar usuários.

Implemente o contexto de tenant na aplicação sem depender de filtros manuais

Centralize a resolução do tenant em middleware, interceptor ou unidade de trabalho. A requisição deve passar por autenticação, autorização da organização e criação de um TenantContext antes de chegar a serviços e repositórios.

O repositório não deve expor métodos perigosos que recebem tenant_id opcionalmente. Prefira interfaces cujo contexto seja obrigatório ou já esteja associado à transação. Isso reduz a chance de uma nova funcionalidade esquecer o filtro.

Nas escritas, ignore ou rejeite um tenant_id enviado pelo cliente quando ele não for necessário. O serviço deve usar o tenant resolvido pela identidade autenticada. A mesma regra vale para uploads, exportações, caches, busca, relatórios e qualquer integração que carregue referências de dados.

Jobs assíncronos e webhooks merecem atenção porque não possuem uma requisição de usuário ativa. Inclua o tenant no payload interno, valide sua origem e estabeleça o contexto antes de abrir a transação. Nunca reutilize contexto de uma execução anterior.

Uma implementação saudável faz com que o caminho seguro seja o caminho mais fácil: contexto por requisição, repositórios com escopo e RLS no banco. Consultas administrativas fora desse fluxo devem ser raras, revisadas e registradas.

Teste cenários de vazamento entre tenants antes do deploy

O teste mais valioso não confirma apenas que um usuário vê seus próprios dados; ele prova que não consegue acessar os dados de outro tenant. Monte fixtures com pelo menos Tenant A e Tenant B, incluindo registros parecidos para evitar falsos positivos.

Para cada endpoint, teste leitura, criação, atualização e exclusão. Tente buscar um identificador do Tenant B usando credenciais do Tenant A, alterar relações para recursos de outro tenant e exportar dados fora do escopo. A resposta deve ser negada ou vazia conforme o contrato da API, sem revelar informações sensíveis.

Teste também busca textual, paginação, dashboards, relatórios, arquivos, notificações, caches e jobs. Falhas de isolamento frequentemente aparecem em caminhos auxiliares que não usam o mesmo repositório principal.

Valide RLS diretamente com a credencial usada pela aplicação. Um teste de integração pode configurar o tenant da transação, inserir dados em ambos os escopos e confirmar que somente as linhas corretas são visíveis. Inclua esses testes no pipeline para impedir regressões.

Para endpoints críticos, adicione testes de propriedade ou fuzzing de identificadores. O objetivo é verificar que qualquer combinação de IDs, parâmetros e papéis mantém a fronteira de isolamento.

Prepare migrações, observabilidade e auditoria para produção

Adicionar isolamento a uma base existente exige uma migração gradual. Primeiro inclua tenant_id permitindo nulos, preencha dados em lotes com uma regra de origem validada, corrija inconsistências e só então aplique NOT NULL, índices, restrições compostas e políticas RLS.

Versione mudanças de schema e políticas como código. Uma política RLS modificada manualmente em produção é difícil de revisar e reproduzir. Cada deploy deve deixar claro quais tabelas foram protegidas e quais exceções são intencionais.

Registre eventos de auditoria com tenant, usuário ou serviço responsável, ação, recurso, horário e resultado. Evite colocar conteúdo sensível, tokens ou dados pessoais desnecessários nos logs. Auditoria precisa ser útil em um incidente sem criar outra superfície de exposição.

Nas métricas, acompanhe volume de requisições, erros de política, latência, consumo e tentativas negadas por tenant. Picos anormais podem indicar defeito, integração mal configurada ou abuso. Alertas devem apontar para o tenant e o componente envolvidos sem expor dados do cliente.

Backups e restaurações também entram no desenho. Documente como recuperar dados sem misturar tenants, como validar um restore e quem está autorizado a executar procedimentos de suporte. O isolamento só é completo quando continua funcionando durante manutenção e incidentes.

Use este checklist de isolamento por tenant para entrar em produção

Antes de liberar uma alteração, revise os controles abaixo em homologação com dados de múltiplos tenants.

  • O tenant é resolvido a partir de uma identidade autenticada e autorizado para a operação.
  • Tabelas de domínio possuem tenant_id obrigatório, índices adequados e restrições contra relações cruzadas.
  • RLS, ou mecanismo equivalente no banco, cobre leitura e escrita e é testado com a credencial da aplicação.
  • Conexões em pool recebem e encerram o contexto de tenant corretamente em cada transação.
  • Endpoints, relatórios, exportações, uploads, cache, webhooks e jobs têm testes de acesso cruzado.
  • Contas administrativas têm regras explícitas, privilégios mínimos e auditoria de acesso entre tenants.
  • Logs, métricas, backups, restaurações e resposta a incidentes foram revisados para o ambiente multi-tenant.

Bloqueie o deploy se um teste de isolamento falhar. Em SaaS, uma falha nessa fronteira não é apenas um defeito funcional: é um evento de segurança e confiança.

Conclusão

Isolamento por tenant em banco compartilhado funciona bem quando é uma propriedade do sistema inteiro, e não uma regra informal em cada consulta. Modele o escopo com tenant_id, derive-o da identidade autenticada, aplique controles no banco, teste tentativas de acesso cruzado e monitore a operação continuamente.

Sua aplicação SaaS precisa crescer sem transformar isolamento de dados em risco operacional. Estruture uma revisão da arquitetura multi-tenant e priorize tenant_id, políticas no banco, testes de acesso cruzado e observabilidade antes do próximo deploy.

M

Max Alex

Criador de conteúdo apaixonado por tecnologia e inovação. Acompanhe nossos artigos para ficar por dentro das melhores estratégias digitais.

Continue lendo