Skip to content

EDD-004 — Estrategia Multi-Tenant y Escalabilidad ​

Metadata ​

CampoValor
AutorAlejandro Maturana
EstadoDRAFT
Fecha2026-07-05
Versión0.2.0
ADRs relacionadosADR-005, ADR-007, ADR-013
RFC relacionadosRFC-0003 (multi-device dashboard)

1. Problema / Contexto ​

Mush2 nació como un sistema monousuario para un solo cultivador y una sola cámara. La arquitectura actual soporta múltiples usuarios y múltiples dispositivos por diseño (modelos User, Chamber, Device, UserChamberAccess), pero no ha sido probada ni optimizada más allá de un escenario de 1–3 dispositivos simultáneos.

El crecimiento natural del proyecto implica:

  1. Multi-cámara (Fase 8): un mismo cultivador con N cámaras físicas
  2. Multi-tenant (potencial): múltiples cultivadores en la misma plataforma, con aislamiento de datos
  3. Marketplace (Fase 16): recetas públicas compartidas entre usuarios

Este EDD captura el diseño de la capa de multi-tenancy y los patrones de escalabilidad que deben establecerse desde ahora para evitar refactors costosos más adelante.


2. Objetivos ​

  • Definir el modelo de aislamiento de datos entre usuarios (row-level vs schema-level)
  • Establecer los límites de escalabilidad del setup actual (Nivel 1: 1–10 dispositivos)
  • Diseñar la evolución hacia Nivel 2 (10–100 dispositivos) sin cambios de arquitectura mayor
  • Garantizar que ningún usuario pueda acceder a datos de otro usuario sin permisos explícitos
  • Documentar los puntos de saturación y cuándo escalar cada capa

3. No-objetivos ​

  • Migración a microservicios (la arquitectura monolítica es intencional para esta escala)
  • Multi-región o geografía distribuida
  • SLA formal con uptime garantizado (el sistema actual es de uso personal/piloto)
  • Billing o facturación por uso

4. Alternativas consideradas ​

4.1 Modelo de aislamiento de datos ​

OpciónProsContrasDecisión
Row-Level Security con userId (elegida)Simple, una sola DB, sin overhead de schemasQueries deben incluir siempre WHERE userId = ?✅ Elegida — implementación actual
Schema-per-tenant (PostgreSQL schemas)Aislamiento fuerte, fácil backup por tenantComplejo de migrar, N schemas = N migraciones❌ excesivo para escala actual
Database-per-tenantAislamiento máximoOperacionalmente inmanejable con muchos tenants❌
Sin aislamiento (shared data)TrivialInaceptable por seguridad❌

4.2 Estrategia de escalabilidad de DB ​

OpciónProsContrasDecisión
Connection pooling + índices (elegida)Sin cambios de arquitecturaLímite ~500 conn. simultáneas✅ Elegida para Nivel 1–2
Read replicasEscala lectura de telemetríaComplejidad operacional alta🟡 Planificada en Nivel 3
TimescaleDB (extension PostgreSQL)Hypertables para time-seriesRequiere migración de esquema🟡 Evaluada en Nivel 3
Sharding horizontalEscala indefinidaMuy complejo, rompe JOIN cross-shard❌ solo Nivel 5+

5. Solución propuesta ​

5.1 Modelo de tenancy actual (Row-Level Security) ​

La tenancy se implementa via middleware y asociaciones de Sequelize:

javascript
// middleware/tenant.js
async function tenantMiddleware(req, res, next) {
  req.userId = req.user.id; // Del JWT decodificado
  req.deviceFilter = {
    include: [
      {
        model: UserChamberAccess,
        where: { userId: req.userId, isActive: true },
      },
    ],
  };
  next();
}

// Uso en controlador
const devices = await Device.findAll({
  ...req.deviceFilter, // Inyectado por middleware
  include: [Chamber],
});

5.2 Niveles de escalabilidad ​

NivelDispositivosUsuariosSetupTelemetría/día
1 — Dev (actual)1–101–5PostgreSQL local, Node.js single process~10K registros
2 — Piloto10–1005–50PostgreSQL dedicado, Node.js + PM2, connection pool~100K registros
3 — Producción100–100050–500PostgreSQL + read replica, TimescaleDB, Redis cache~1M registros
4 — Scale1000–10K500–5KKubernetes, múltiples instancias, MQTT propio~10M registros
5 — Industrial10K+5K+Sharding, CDN, microservicios por dominio~100M registros

5.3 Puntos de saturación y triggers de escala ​

Nivel 1 → Nivel 2 (triggers):
  - API p95 > 500ms sostenido
  - Telemetría DB > 50GB
  - > 10 usuarios concurrentes con SSE

Nivel 2 → Nivel 3 (triggers):
  - Connection pool exhausto (> 20 conn.)
  - Queries de telemetría histórica > 2s
  - > 100 dispositivos con polling simultáneo

5.4 Retención de datos de telemetría ​

Para evitar crecimiento indefinido de la tabla Telemetry:

sql
-- Política de retención (a implementar en Fase 14)
-- Raw data: retener 30 días
DELETE FROM "Telemetries"
WHERE "createdAt" < NOW() - INTERVAL '30 days';

-- Agregados horarios: retener 1 año
-- (implementar con pg_cron o job de Node.js)
INSERT INTO "TelemetryHourly" (deviceId, hour, avg_temp, avg_humidity, avg_co2)
SELECT deviceId, DATE_TRUNC('hour', timestamp), AVG(value)...

5.5 Roles y permisos (RBAC actual) ​

SUPER_ADMIN
  └── Acceso completo a todo
ADMIN
  └── Gestión de usuarios en su organización
OPERATOR
  └── Control de dispositivos asignados via UserChamberAccess
VIEWER
  └── Solo lectura de dispositivos asignados

6. Impacto en componentes ​

ComponenteImpacto nivel actualImpacto nivel 2+
Backend✅ Implementado (middleware tenant)Requiere connection pooling explícito
Base de datos✅ Índices básicosRequiere índices en deviceId + timestamp
Frontend✅ Filtrado por usuarioRequiere paginación de telemetría
FirmwareSin impacto (aislado por deviceId)Sin impacto
InfraestructuraSolo dev localNivel 2: VM dedicada + Nginx

7. Plan de implementación ​

Fase actual (Nivel 1 — completado) ​

  • [x] Middleware de tenant con userId
  • [x] UserChamberAccess para asociación usuario-dispositivo
  • [x] RBAC con 4 roles (ADR-007)
  • [x] Audit logging de operaciones sensibles

Fase 8 — Multi-cámara (Nivel 1+) ​

  • [ ] Frontend: selector de dispositivo y vista multi-dispositivo
  • [ ] Backend: rutas multi-device sin cambiar arquitectura
  • [ ] Test con 3 ESP32 simultáneos

Fase 9+ — Nivel 2 ​

  • [ ] Connection pooling configurado (pgBouncer o Sequelize pool)
  • [ ] Índices en Telemetry(deviceId, createdAt)
  • [ ] Retención de datos con job programado
  • [ ] MQTT broker propio (elimina dependencia de brokers públicos)

8. Métricas de éxito ​

MétricaNivel 1Nivel 2
Usuarios aislados correctamente✅✅
Peticiones concurrentes sin error~50~500
Telemetría query < 200ms✅ (datos pequeños)Requiere índices
Dispositivos simultáneos1–310–100

9. Riesgos y mitigaciones ​

RiesgoProb.ImpactoMitigación
Middleware de tenant olvidado en nuevo endpointMediaAltoLinting + tests de autorización obligatorios
Crecimiento de telemetría satura discoMediaAltoPolítica de retención en Fase 14
MQTT broker público no disponibleAltaMedioFase 9: broker propio
N+1 queries en listados multi-deviceMediaMedioEager loading con Sequelize include

10. Referencias ​

Mush2 — Sistema IoT de control ambiental