Este documento visa definir as melhores práticas e tecnologias para o desenvolvimento do backend do projeto MN2J, especialmente no que tange a:
Estruturação multi-tenant escalável e segura;
Estratégias modernas de autenticação e autorização;
Modelagem de dados, migrações e consultas eficientes;
Justificativas técnicas para escolhas estratégicas.
2. Metodologia Multi-Tenant Recomendada
2.1. Abordagem recomendada: Shared Database + Shared Schema com Tenant ID
Definição:
Todas as entidades no banco de dados possuem um campo obrigatório tenant_id (UUID/string), que indica a qual tenant (cliente, anfitrião ou empresa) aquele registro pertence.
Por que essa abordagem?
Escalabilidade: Funciona bem para milhares a milhões de tenants.
Simplicidade: Facilita manutenção, migrações e deploys.
Custo: Reduz custos operacionais, usando um único banco de dados.
Segurança: Pode ser reforçada com Row Level Security (RLS) no PostgreSQL e regras no backend.
Prática do mercado: Grandes players (ex: Airbnb) adotam essa abordagem.
2.2 Outras abordagens (não recomendadas para MN2J atualmente)
Abordagem
Quando usar?
Por que evitar no MN2J agora?
Tenant-per-schema
Empresas B2B com poucos tenants
Complexidade de migração e manutenção
Tenant-per-database
Enterprise, compliance estrita
Custo e complexidade elevados
Keycloak (multi-realm)
Enterprise, sistemas internos
Overkill para app público; integrações complexas
3. Tecnologias Recomendadas
Componente
Tecnologia Sugerida
Motivação
Backend
Node.js com NestJS
Framework modular, robusto e suporte a Middleware
ORM
Prisma ORM
Tipagem segura, fácil integração multi-tenant
Banco de Dados
PostgreSQL
Suporte a RLS, JSONB, escalável, confiável
Cache
Redis
Sessões, filas (Bull), cache
Autenticação
JWT + Passport.js
Leve, flexível, sob controle, integra fácil
Storage
AWS S3 (produção) / local (MVP)
Armazenamento escalável de arquivos/imagens
CI/CD
GitHub Actions
Automação de testes e deploys
4. Modelagem de Dados: Exemplo Multi-Tenant
4.1 Exemplo: Tabela Booking
CREATE TABLE bookings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
user_id UUID NOT NULL,
space_id UUID NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
status VARCHAR(50),
created_at TIMESTAMP DEFAULT now(),
updated_at TIMESTAMP DEFAULT now()
);
CREATE INDEX idx_bookings_tenant ON bookings (tenant_id);
tenant_id: identifica o cliente dono da reserva
user_id: quem fez a reserva
space_id: o espaço reservado
4.2 Exemplo: Relação User e Tenant
CREATE TABLE tenants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
plan VARCHAR(50) DEFAULT 'free',
created_at TIMESTAMP DEFAULT now()
);
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id),
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
role VARCHAR(50) DEFAULT 'user',
created_at TIMESTAMP DEFAULT now()
);
CREATE INDEX idx_users_tenant ON users (tenant_id);
5. Migrações Tenant-Aware
Usar ferramentas como Prisma Migrate, Knex, ou TypeORM migrations.
Como usamos shared schema, aplicamos as migrações uma vez para todos os tenants.
Para schema-per-tenant, migrações são aplicadas automaticamente no provisionamento de cada novo tenant.
Sempre testar migrações em ambiente staging antes do deploy.
6. Estratégias Modernas de Consulta e APIs
APIs RESTful ou GraphQL que aceitem o token JWT com tenant_id.
Backend valida e injeta o tenant_id nas queries automaticamente (ex: via middleware).
Indexar colunas tenant_id para performance.
Uso futuro de Elasticsearch para buscas avançadas.
7. Autenticação e Justificativa para Não Usar Keycloak
Aspecto
Keycloak
JWT + Passport.js (Recomendado)
Complexidade
Alta — Setup e manutenção
Baixa — integração direta no NestJS
Customização UX
Difícil
Totalmente customizável no frontend
Multi-tenant
Multi-realm, porém pesado
Controle nativo com tenant_id no token
Custo
Alto (infra + manutenção)
Baixo (infra mínima)
Experiência do usuário
Pode ser pesada
Ágil e simples
Resumo:
Para MN2J, que é uma plataforma pública B2C com milhares de usuários e tenants, usar JWT com Passport em NestJS é a abordagem mais leve, flexível e econômica, mantendo o controle total sobre o fluxo.
8. Considerações Finais e Próximos Passos
Definir schema inicial com tenant_id obrigatório.
Criar middleware/guard NestJS para resolver tenant via JWT.
Configurar Prisma para aplicar filtros multi-tenant automaticamente.
Implementar migrações e testes completos.
Construir painel admin para criação/controle de tenants.
Monitorar e ajustar performance conforme crescimento.