platform-marketing-content/docs/97-adr/ADR-002-multi-tenancy.md

3.3 KiB

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

-- 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

  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


Documento generado por: Requirements-Analyst Fecha: 2025-12-08