Estratégias de isolamento de tenants em infraestrutura compartilhada
1. Fundamentos do modelo multitenant
Em arquiteturas multitenant, um tenant representa um cliente ou unidade organizacional que compartilha a mesma infraestrutura de software, hardware e dados com outros inquilinos. O desafio central é garantir que cada tenant opere como se estivesse em um ambiente dedicado, sem comprometer a eficiência de recursos.
Os trade-offs fundamentais são claros: isolamento máximo (menor densidade, maior custo) versus eficiência de recursos (maior densidade, menor isolamento). A classificação típica inclui:
- Isolamento hard: recursos completamente dedicados (VMs, bancos separados)
- Isolamento soft: recursos compartilhados com mecanismos lógicos de separação (tenant_id, namespaces)
- Isolamento híbrido: combinação de ambos, como banco dedicado para tenants premium e compartilhado para os demais
A escolha correta depende de requisitos de segurança, compliance e orçamento.
2. Isolamento por camada de banco de dados
Bancos de dados separados por tenant
Cada tenant possui seu próprio banco de dados. Exemplo de configuração:
# Configuração de conexão por tenant (exemplo conceitual)
tenants:
tenant_a:
host: db-tenant-a.internal
database: erp_tenant_a
user: app_tenant_a
tenant_b:
host: db-tenant-b.internal
database: erp_tenant_b
user: app_tenant_b
Schema por tenant
Um banco compartilhado com schemas separados:
CREATE SCHEMA tenant_123;
CREATE SCHEMA tenant_456;
CREATE TABLE tenant_123.orders (
id SERIAL PRIMARY KEY,
product TEXT,
amount DECIMAL
);
CREATE TABLE tenant_456.orders (
id SERIAL PRIMARY KEY,
product TEXT,
amount DECIMAL
);
Tabelas compartilhadas com Row Level Security (RLS)
O PostgreSQL RLS filtra automaticamente por tenant_id:
-- Habilitar RLS na tabela
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- Criar política de isolamento
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.current_tenant')::INT);
-- Configurar o tenant na sessão
SET app.current_tenant = '123';
SELECT * FROM orders; -- Retorna apenas registros do tenant 123
3. Isolamento em nível de aplicação
Middleware de roteamento baseado em tenant
Em frameworks web, um middleware intercepta requisições e injeta o contexto do tenant:
# Exemplo de middleware (pseudocódigo)
class TenantMiddleware:
def process_request(self, request):
tenant_id = self.extract_from_header(request, 'X-Tenant-ID')
if not tenant_id:
return error_response("Tenant não identificado", 400)
# Configurar contexto global da requisição
request.tenant = TenantContext(tenant_id)
# Configurar conexão de banco específica
request.db_connection = self.get_db_for_tenant(tenant_id)
# Configurar cache isolado
request.cache_prefix = f"tenant:{tenant_id}:"
Contextos de execução isolados
Para evitar que um tenant consuma recursos de outro, use thread pools ou corrotinas dedicadas:
# Pool de threads por tenant
tenant_pools = {
"premium": ThreadPoolExecutor(max_workers=10),
"standard": ThreadPoolExecutor(max_workers=4),
"basic": ThreadPoolExecutor(max_workers=1)
}
def process_request(tenant_id, task):
pool = tenant_pools.get(tenant_id, tenant_pools["basic"])
future = pool.submit(task)
return future.result()
Cache e sessões segregados
Prefixos de chave no Redis garantem isolamento:
# Redis com prefixo por tenant
SET tenant:123:session:abc456 "dados_sessao"
SET tenant:456:session:def789 "dados_sessao"
# Cache de dados
SET tenant:123:cache:produtos "[...]"
SET tenant:456:cache:produtos "[...]"
4. Isolamento em infraestrutura de mensageria e filas
Tópicos/streams dedicados por tenant
No NATS JetStream, crie streams separados:
# Criação de streams por tenant
nats stream add orders_tenant_a --subjects "tenant.a.orders.*"
nats stream add orders_tenant_b --subjects "tenant.b.orders.*"
# Políticas de retenção distintas
nats stream update orders_tenant_a --max-age=30d
nats stream update orders_tenant_b --max-age=7d
Controle de throughput e backpressure
Configure consumidores com limites específicos:
# Consumidor com backpressure por tenant
nats consumer add orders_tenant_a worker \
--max-deliver=3 \
--max-pending=100 \
--ack-wait=30s
5. Isolamento em armazenamento de objetos e arquivos
Buckets separados por tenant
No S3 ou compatíveis:
# Buckets dedicados
s3://tenant-a-uploads/
s3://tenant-b-uploads/
# Políticas IAM restritivas
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::tenant-a-uploads/*",
"Condition": {
"StringEquals": {"aws:PrincipalTag/tenant": "tenant-a"}
}
}
]
}
Prefixos com políticas de acesso
Alternativa com um bucket único:
# Prefixos organizados
s3://shared-bucket/tenant-a/files/
s3://shared-bucket/tenant-b/files/
# Política baseada em prefixo
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::shared-bucket/tenant-a/*"
}
Criptografia com chaves por tenant
Use AWS KMS com chaves gerenciadas pelo cliente:
# Criptografia no upload
aws s3 cp documento.pdf s3://tenant-a-uploads/ \
--sse aws:kms \
--sse-kms-key-id arn:aws:kms:us-east-1:123456789012:key/tenant-a-key
6. Monitoramento e observabilidade multitenant
Métricas segregadas
Use labels ou tags para identificar o tenant:
# Prometheus metrics com label tenant
http_requests_total{tenant="tenant_a", status="200"} 1500
http_requests_total{tenant="tenant_b", status="200"} 2300
http_request_duration_seconds{tenant="tenant_a"} 0.045
# Alertas específicos
ALERT HighErrorRateTenantA
IF rate(http_requests_total{tenant="tenant_a", status="5xx"}[5m]) > 0.05
LABELS { severity = "critical" }
Logs estruturados
Inclua o tenant_id em todos os logs:
{
"timestamp": "2025-01-15T10:30:00Z",
"level": "ERROR",
"tenant_id": "tenant_a",
"service": "checkout",
"message": "Falha no pagamento",
"request_id": "req-abc-123"
}
7. Governança e operações em ambientes compartilhados
Rate limiting e quotas
Implemente limites por tenant:
# Configuração de rate limit
rate_limits:
tenant_a:
requests_per_second: 1000
concurrent_connections: 50
storage_gb: 100
tenant_b:
requests_per_second: 100
concurrent_connections: 10
storage_gb: 20
Backup com isolamento
Estratégias de backup que respeitam os limites:
# Backup por tenant
pg_dump -h db-host -d erp_tenant_a > backup_tenant_a.sql
pg_dump -h db-host -d erp_tenant_b > backup_tenant_b.sql
# Restauração seletiva
pg_restore -d erp_tenant_a_new backup_tenant_a.sql
8. Segurança e conformidade no modelo multitenant
Prevenção de vazamento de dados
Validação de tenant_id em todas as consultas:
# Consulta segura (sempre filtrar por tenant)
SELECT * FROM orders
WHERE tenant_id = $1 AND id = $2;
# Evitar consultas sem filtro de tenant
SELECT * FROM orders; # PERIGOSO - retorna dados de todos os tenants
Auditoria e rastreabilidade
Registre todas as operações por tenant:
CREATE TABLE audit_log (
id SERIAL PRIMARY KEY,
tenant_id INT NOT NULL,
user_id INT,
action TEXT,
resource TEXT,
timestamp TIMESTAMPTZ DEFAULT NOW()
);
-- Índice para consultas por tenant
CREATE INDEX idx_audit_tenant ON audit_log(tenant_id, timestamp);
Compliance com regulamentações
Para LGPD, GDPR e HIPAA, o isolamento é crítico:
- LGPD: Direito de exclusão de dados requer capacidade de deletar todos os dados de um tenant sem afetar outros
- GDPR: Portabilidade exige exportação isolada dos dados do tenant
- HIPAA: Logs de acesso devem ser segregados e auditáveis por tenant
Implemente funções de gerenciamento de ciclo de vida:
-- Função para exclusão completa de tenant (LGPD/GDPR)
CREATE OR REPLACE FUNCTION delete_tenant_data(p_tenant_id INT)
RETURNS VOID AS $$
BEGIN
DELETE FROM orders WHERE tenant_id = p_tenant_id;
DELETE FROM users WHERE tenant_id = p_tenant_id;
DELETE FROM audit_log WHERE tenant_id = p_tenant_id;
-- Limpar cache e armazenamento externo
PERFORM clean_tenant_storage(p_tenant_id);
END;
$$ LANGUAGE plpgsql;
Referências
-
AWS Multi-Tenant Isolation Patterns — Documentação oficial da AWS sobre padrões de isolamento em arquiteturas SaaS, incluindo estratégias de banco, armazenamento e rede.
-
PostgreSQL Row Level Security Documentation — Guia completo do PostgreSQL sobre RLS, com exemplos práticos de políticas de isolamento por tenant.
-
NATS JetStream Multi-Tenancy — Documentação oficial sobre como configurar streams isolados por tenant no NATS JetStream, com exemplos de configuração.
-
Redis Multi-Tenant Cache Strategies — Melhores práticas para nomeação de chaves no Redis, essencial para isolamento de cache entre tenants.
-
Google Cloud Armor - Rate Limiting per Tenant — Tutorial sobre implementação de rate limiting e quotas por tenant usando Google Cloud Armor e políticas personalizadas.
-
HIPAA Compliance in Multi-Tenant Environments — Guia oficial do HHS sobre requisitos de segurança HIPAA em ambientes compartilhados, com foco em isolamento de dados de saúde.
-
GDPR Data Portability and Multi-Tenant Systems — Artigo 20 do GDPR sobre direito à portabilidade, com implicações práticas para arquiteturas multitenant.