- Update vision, architecture and technical documentation - Update module definitions (PMC-001 to PMC-008) - Update requirements documentation - Add CONTEXT-MAP.yml and ENVIRONMENT-INVENTORY.yml - Add orchestration guidelines and references 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
156 lines
3.6 KiB
Markdown
156 lines
3.6 KiB
Markdown
---
|
|
id: "ADR-002"
|
|
title: "Estrategia de Multi-Tenancy"
|
|
type: "ADR"
|
|
status: "Accepted"
|
|
date: "2025-12-08"
|
|
deciders: ["Architecture Team"]
|
|
tags: ["database", "rls", "multitenancy", "security"]
|
|
project: "platform_marketing_content"
|
|
created_date: "2025-12-08"
|
|
updated_date: "2026-01-04"
|
|
---
|
|
|
|
# ADR-002: Estrategia de Multi-Tenancy
|
|
|
|
**Fecha:** 2025-12-08
|
|
**Estado:** Aceptado
|
|
|
|
---
|
|
|
|
## Contexto
|
|
|
|
La plataforma debe soportar múltiples organizaciones (tenants) con:
|
|
|
|
1. Aislamiento completo de datos entre tenants
|
|
2. Configuración personalizable por tenant
|
|
3. Posibilidad de escalar a SaaS público
|
|
4. Costos operativos manejables
|
|
|
|
Opciones de multi-tenancy:
|
|
- **Database per tenant:** Una BD por cada tenant
|
|
- **Schema per tenant:** Un schema por tenant en misma BD
|
|
- **Shared schema:** Todos en mismas tablas con tenant_id
|
|
|
|
---
|
|
|
|
## Decisión
|
|
|
|
### Estrategia: Shared Schema con Row-Level Security (RLS)
|
|
|
|
Usaremos una sola base de datos con esquemas funcionales (auth, crm, projects, etc.) donde todas las tablas tienen columna `tenant_id` y políticas RLS que filtran automáticamente.
|
|
|
|
### Implementación
|
|
|
|
```sql
|
|
-- Columna tenant_id en todas las tablas principales
|
|
ALTER TABLE crm.clients ADD COLUMN tenant_id UUID NOT NULL;
|
|
|
|
-- Política RLS
|
|
CREATE POLICY tenant_isolation ON crm.clients
|
|
USING (tenant_id = current_setting('app.current_tenant')::uuid);
|
|
|
|
-- Habilitar RLS
|
|
ALTER TABLE crm.clients ENABLE ROW LEVEL SECURITY;
|
|
```
|
|
|
|
### Middleware de Tenant
|
|
|
|
```typescript
|
|
@Injectable()
|
|
export class TenantMiddleware implements NestMiddleware {
|
|
async use(req: Request, res: Response, next: NextFunction) {
|
|
const tenantId = this.extractTenantFromJwt(req);
|
|
|
|
// Set para la conexión actual
|
|
await this.dataSource.query(
|
|
`SET app.current_tenant = '${tenantId}'`
|
|
);
|
|
|
|
next();
|
|
}
|
|
}
|
|
```
|
|
|
|
### Storage Isolation
|
|
|
|
```
|
|
bucket/
|
|
├── {tenant_slug}/
|
|
│ ├── assets/
|
|
│ ├── models/
|
|
│ └── temp/
|
|
```
|
|
|
|
---
|
|
|
|
## Consecuencias
|
|
|
|
### Positivas
|
|
|
|
- **Un solo deployment:** Una instancia sirve a todos los tenants
|
|
- **Costos reducidos:** No hay overhead de múltiples BDs
|
|
- **Mantenimiento simple:** Migraciones se aplican una vez
|
|
- **RLS nativo:** PostgreSQL garantiza aislamiento a nivel de motor
|
|
- **Queries simples:** No hay JOINs entre BDs/schemas
|
|
- **Escalabilidad:** Read replicas y sharding posibles
|
|
|
|
### Negativas
|
|
|
|
- **Complejidad de RLS:** Requiere configurar políticas en cada tabla
|
|
- **Risk de bug:** Error en middleware podría filtrar datos incorrectos
|
|
- **Backups:** No hay backups por tenant (todo junto)
|
|
- **Noisy neighbors:** Un tenant pesado afecta a todos
|
|
|
|
### Mitigaciones
|
|
|
|
1. **Tests exhaustivos** de RLS en cada tabla
|
|
2. **Logs de auditoría** de todas las queries con tenant_id
|
|
3. **Rate limiting** por tenant
|
|
4. **Monitoring** de queries lentas por tenant
|
|
|
|
---
|
|
|
|
## Alternativas Consideradas
|
|
|
|
### 1. Database per Tenant
|
|
|
|
**Pros:**
|
|
- Aislamiento completo
|
|
- Backups individuales
|
|
- Fácil de escalar por tenant
|
|
|
|
**Contras:**
|
|
- Costos altos (una BD por cliente)
|
|
- Complejidad de deployment
|
|
- Migraciones en múltiples BDs
|
|
- Connection pooling complejo
|
|
|
|
**Rechazo:** Costos prohibitivos para MVP
|
|
|
|
### 2. Schema per Tenant
|
|
|
|
**Pros:**
|
|
- Buen aislamiento
|
|
- Una sola BD
|
|
- Backups parciales posibles
|
|
|
|
**Contras:**
|
|
- Migraciones en múltiples schemas
|
|
- Límite de schemas en PostgreSQL
|
|
- Complejidad de routing
|
|
|
|
**Rechazo:** Complejidad sin beneficio claro sobre RLS
|
|
|
|
---
|
|
|
|
## Referencias
|
|
|
|
- [PostgreSQL RLS Documentation](https://www.postgresql.org/docs/current/ddl-rowsecurity.html)
|
|
- [Multi-tenant SaaS patterns](https://docs.microsoft.com/en-us/azure/architecture/guide/multitenant/)
|
|
|
|
---
|
|
|
|
**Documento generado por:** Requirements-Analyst
|
|
**Fecha:** 2025-12-08
|