- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8 - Actualizaciones de configuracion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4.2 KiB
4.2 KiB
| id | title | type | status | priority | supersedes | superseded_by | version | created_date | updated_date |
|---|---|---|---|---|---|---|---|---|---|
| ADR-001 | Multi-tenancy con PostgreSQL Row-Level Security | ADR | Accepted | P0 | N/A | N/A | 1.0.0 | 2026-01-07 | 2026-01-10 |
ADR-001: Multi-tenancy con PostgreSQL Row-Level Security
Metadata
| Campo | Valor |
|---|---|
| ID | ADR-001 |
| Estado | Accepted |
| Fecha | 2026-01-10 |
| Supersede | N/A |
Contexto
Template SaaS requiere soporte para múltiples organizaciones (tenants) en una misma instancia de la aplicación. Cada tenant debe tener sus datos completamente aislados de otros tenants por razones de seguridad y privacidad.
Requisitos
- Aislamiento completo de datos entre tenants
- Escalabilidad para miles de tenants
- Simplicidad operacional (un solo deployment)
- Performance consistente
- Facilidad de backup/restore por tenant
Opciones Consideradas
Opción 1: Database per Tenant
Descripción: Cada tenant tiene su propia base de datos PostgreSQL.
Pros:
- Aislamiento total de datos
- Fácil backup/restore individual
- Sin riesgo de data leaks entre tenants
Contras:
- Complejidad operacional alta (miles de DBs)
- Connection pooling complejo
- Migraciones costosas (aplicar a cada DB)
- Mayor costo de infraestructura
Opción 2: Schema per Tenant
Descripción: Cada tenant tiene su propio schema dentro de una base de datos.
Pros:
- Mejor aislamiento que shared tables
- Backup/restore por schema posible
- Un solo connection pool
Contras:
- Migraciones aún costosas
- Límite práctico de schemas (~10,000)
- Complejidad en queries cross-tenant
Opción 3: Row-Level Security (RLS) ✓
Descripción: Todos los tenants comparten las mismas tablas, con políticas RLS que filtran por tenant_id.
Pros:
- Operacionalmente simple
- Un solo set de tablas y migraciones
- Escalable a millones de tenants
- Performance optimizado con índices
- Queries simples y consistentes
Contras:
- Riesgo de data leaks si RLS mal configurado
- Requiere disciplina en desarrollo
- Backup individual más complejo
Decisión
Elegimos Row-Level Security (RLS) por las siguientes razones:
- Simplicidad Operacional: Un solo deployment, una base de datos, un set de migraciones
- Escalabilidad: Soporta desde 1 hasta millones de tenants sin cambios arquitectónicos
- Performance: PostgreSQL RLS es eficiente y se beneficia de índices
- Costo: Menor infraestructura requerida
Implementación
Estructura de Tablas
Todas las tablas multi-tenant incluyen:
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id)
Políticas RLS
-- Ejemplo para tabla users
ALTER TABLE users.users ENABLE ROW LEVEL SECURITY;
CREATE POLICY users_tenant_isolation ON users.users
USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
Context Setting
El tenant_id se establece en cada request:
SET app.current_tenant_id = 'uuid-del-tenant';
Middleware NestJS
@Injectable()
export class TenantContextInterceptor implements NestInterceptor {
async intercept(context: ExecutionContext, next: CallHandler) {
const request = context.switchToHttp().getRequest();
const tenantId = request.user?.tenant_id;
await this.dataSource.query(
`SET app.current_tenant_id = '${tenantId}'`
);
return next.handle();
}
}
Consecuencias
Positivas
- Código más simple y mantenible
- Un solo esquema de datos
- Migraciones atómicas
- Queries sin WHERE tenant_id manual
- Escalabilidad lineal
Negativas
- Requiere testing exhaustivo de RLS
- Datos de todos los tenants en mismas tablas
- Backup por tenant requiere queries filtradas
- Posible contención en tablas muy grandes
Mitigaciones
- Tests automatizados de aislamiento
- Auditoría de queries en desarrollo
- Particionamiento por tenant_id si necesario
- Monitoreo de performance por tenant
Referencias
- PostgreSQL RLS Documentation
- Multi-tenancy Patterns
- Schema DDL:
apps/database/ddl/schemas/
Fecha decision: 2026-01-10 Autores: Claude Code (Arquitectura)