Em mais de duas décadas desenvolvendo soluções em Java, tive a oportunidade de atuar na arquitetura de diversos sistemas SaaS. Alguns deles nasceram pequenos e escalaram rápido. Outros começaram grandes e precisaram de uma base sólida desde o primeiro deploy. Em todos, um desafio se repetiu: como construir uma arquitetura SaaS multitenant segura, escalável e sustentável no médio/longo prazo?
Neste artigo, compartilho como tenho estruturado esse tipo de plataforma usando Java com Quarkus, AWS e boas práticas que aprendi liderando times técnicos em produtos reais.
1. O que é SaaS Multitenant?
Vamos começar do começo. SaaS (Software as a Service) é um software que você oferece para várias empresas (clientes), geralmente pela internet. Multitenant significa que múltiplas empresas usam a mesma aplicação, mas cada uma vê e acessa apenas seus próprios dados.
Pense como um prédio com vários apartamentos: todos compartilham o mesmo prédio, mas cada morador tem sua chave e seu espaço.
O desafio está em garantir que:
- Um cliente não veja dados de outro
- Possamos isolar acessos, configurações e recursos
- Escalemos sem precisar duplicar o sistema inteiro para cada novo cliente
2. Arquitetura Base com Java, Quarkus e AWS
Tecnologias que costumo usar:
- Java + Quarkus: para ganhar performance e inicialização rápida
- PostgreSQL (RDS): banco de dados relacional da AWS
- Amazon Cognito: faz o login/autenticação dos usuários
- S3 + CloudFront: para guardar arquivos e entregar conteúdo rápido
- SQS e SNS: para comunicação entre partes do sistema sem travar tudo (eventos assíncronos)
- SSM Parameter Store: para guardar senhas e configs com segurança
- Terraform + GitHub Actions: para criar infraestrutura e fazer deploy automático
Estrutura do projeto:
core
: onde ficam as regras de negócio (ex: cadastro de usuário, geração de relatórios)infra
: onde ficam os acessos ao banco, Cognito, S3, etc.usecases
: os casos de uso do sistema (ex: CriarTenantUseCase)api
: onde expomos os endpoints REST (ex:/v1/login
)
3. Como isolar os dados de cada cliente
Imagine que você tem 3 clientes: Empresa A, Empresa B e Empresa C.
Você pode escolher entre:
- Um banco diferente para cada empresa
- Um único banco com um schema para cada empresa
- Um único banco com uma coluna “tenant_id” em todas as tabelas
Eu costumo usar a opção 3. Ela é mais simples de escalar, fácil de manter e permite centralizar os dados com controle via código. Em cada tabela do banco, adicionamos uma coluna tenant_id
.
Como funciona na prática:
- Exemplo de tabela:
CREATE TABLE usuarios ( id SERIAL PRIMARY KEY, nome TEXT NOT NULL, email TEXT NOT NULL, tenant_id TEXT NOT NULL );
- Toda consulta ou inserção no banco inclui o
tenant_id
.
SELECT * FROM usuarios WHERE tenant_id = 'empresa_a';
- No código, usamos filtros automáticos para evitar esquecer esse controle:
TypedQuery<Usuario> q = em.createQuery("SELECT u FROM Usuario u WHERE u.tenantId = :tenantId", Usuario.class); q.setParameter("tenantId", tenantAtual);
- Em frameworks como Hibernate, podemos usar interceptadores ou
EntityListeners
para adicionar otenant_id
automaticamente em cada operação.
Diagrama:
+-------------------------+ | TABELA USUARIOS | +-------------------------+ | id | 123 | | nome | João | | email | joao@x.com | | tenant_id | empresa_a | +-------------------------+
Vantagens dessa abordagem:
- Escala muito bem
- Mais simples de gerenciar
- Código único para todos os tenants
Desvantagens:
- Requer atenção redobrada no controle de acesso
- Não há isolamento físico, apenas lógico
Mas com boas práticas e validações, funciona muito bem.
4. Como fazer login com AWS Cognito
O Cognito é como se fosse um “login do Google” para o seu sistema. Você não precisa criar toda a lógica de autenticação, reset de senha, confirmação de e-mail, etc.
Como funciona:
- Criamos um “User Pool” no Cognito (tipo uma base de usuários)
- Cada usuário novo é criado lá, com o e-mail, senha, e o
company_id
- Quando o usuário faz login, o Cognito devolve um token JWT com essas infos
No backend Java, usamos esse token para saber quem está acessando e a qual empresa pertence.
Configuração no Quarkus:
mp.jwt.verify.publickey.location=https://cognito-idp.sa-east-1.amazonaws.com/<pool_id>/.well-known/jwks.json quarkus.oidc.enabled=true
Diagrama de fluxo:

5. Deploy automatizado por cliente com Terraform e GitHub Actions
Quando um novo cliente entra na plataforma, criamos automaticamente:
- Bucket no S3 para guardar arquivos desse cliente
- Entrada no SSM com as configs dele
- Subdomínio no Route 53 (ex:
empresa-a.sistema.com
) - Parametrização no backend com
tenant_id
Como fazer isso:
- Usamos Terraform com variáveis por tenant
- Criamos workflows no GitHub Actions que, ao detectar uma mudança ou nova empresa, executam a criação de tudo automaticamente
Diagrama:
[GitHub Actions] | | --> [Terraform Apply com tenant_id] | | | |--> cria Bucket S3 | |--> cria entradas no SSM | |--> cria subdomínio
6. Como medir o uso e fazer billing (cobrança)
Você pode cobrar por:
- Número de usuários ativos
- Quantidade de relatórios gerados
- Espaço usado em disco
- Número de requisições
Como registrar o uso:
- Criamos uma tabela
usage_log
CREATE TABLE usage_log ( tenant_id TEXT, action TEXT, timestamp TIMESTAMP DEFAULT now() );
- Cada vez que algo importante acontece, gravamos um log ali
Como cobrar:
- Uma Lambda executa todo dia 1 e conta os logs do mês anterior
- Disparamos uma cobrança com Stripe ou outro meio de pagamento
Diagrama:

7. Lições práticas que aprendi
- Sempre tenha logs separados por empresa (ajuda no suporte)
- Evite criar código fixo para um cliente: use configs e feature flags
- Guarde tudo com rastro:
tenant_id
,user_id
, horário, IP - Controle bem os acessos de “admin do sistema”
- Comece simples, mas pensando em crescimento
Conclusão
Criar um sistema SaaS multitenant parece complexo, mas fica mais fácil com os conceitos certos e ferramentas adequadas. Com Java, Quarkus e AWS conseguimos montar uma base sólida, segura e escalável.
Se você está começando um SaaS ou tem um sistema que precisa evoluir, espero que esse guia te ajude. Se quiser trocar uma ideia sobre arquitetura ou tirar dúvidas, é só me chamar por aqui!