- 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>
3.6 KiB
3.6 KiB
| id | title | type | status | date | deciders | tags | project | created_date | updated_date | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ADR-002 | Estrategia de Multi-Tenancy | ADR | Accepted | 2025-12-08 |
|
|
platform_marketing_content | 2025-12-08 | 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:
- Aislamiento completo de datos entre tenants
- Configuración personalizable por tenant
- Posibilidad de escalar a SaaS público
- 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
-- 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
@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
- Tests exhaustivos de RLS en cada tabla
- Logs de auditoría de todas las queries con tenant_id
- Rate limiting por tenant
- 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
Documento generado por: Requirements-Analyst Fecha: 2025-12-08