CreaRack-SL

Capacity Planning - CreaRack Pro SaaS

Capacity Planning - CreaRack Pro SaaS

Guia de planificacion de capacidad para despliegue en produccion. Incluye analisis de almacenamiento VictoriaMetrics, consumo por tenant y recomendaciones por tier de servidor.

Ultima actualizacion: 06-02-2026 Version: v6.5.8


1. VictoriaMetrics - Metricas y Almacenamiento

1.1 Metricas escritas por dispositivo

Cada dispositivo monitorizado genera 7 time series en VictoriaMetrics:

TipoMetricaDescripcion
Pingping_latency_msRTT en milisegundos
Pingping_packet_loss_percentPerdida de paquetes (0-100)
Pingping_reachable1/0 (alcanzable o no)
SNMPsnmp_bandwidth_in_mbpsAncho de banda entrante
SNMPsnmp_bandwidth_out_mbpsAncho de banda saliente
HTTPhttp_response_time_msTiempo de respuesta HTTP
HTTPhttp_status_codeCodigo de estado HTTP

Labels por metrica: tenant_id, target_id, target_ip (aislamiento multi-tenant).

Formato de escritura: JSON newline-delimited via /api/v1/import (fire-and-forget, no bloquea HTTP).

1.2 Fuentes de metricas en VM

VictoriaMetrics almacena datos de 3 fuentes distintas, configuradas en observability/victoriametrics/scrape.yml:

JobSeriesIntervaloProposito
victoriametrics (self)~1,48460sAuto-telemetria de VM (Go runtime, cache, merges)
crearack-web (Django)~51960sLatencias HTTP, request counts por view/method
crearack-health~730sHealth check basico
Monitoreo devices7 × N deviceson-demandMetricas de dispositivos (ping/snmp/http)

Optimizacion aplicada (06-02-2026): Los intervalos de scrape de VM self y Django se redujeron de 15s/10s a 60s/60s. Esto reduce el overhead de infraestructura de ~2.3 GB a ~512 MB en 180 dias, sin impacto en la operativa.

1.3 Compresion de VictoriaMetrics

VM comprime time series a ~0.5-1.5 bytes por data point (media ~1 byte). Esto es una de sus principales ventajas frente a Prometheus.

Formula de calculo:

Almacenamiento = series × (86400 / intervalo_segundos) × dias × 1 byte

1.4 Almacenamiento por dispositivo

Con refresh de 5s (el mas agresivo del Observatory):

7 metricas × 17,280 writes/dia = ~120,960 puntos/dia × 1 byte = ~120 KB/dia/device
Dispositivos30 dias90 dias180 dias
1~3.5 MB~10.5 MB~21 MB
50~175 MB~525 MB~1 GB
100~350 MB~1 GB~2.1 GB
200~700 MB~2.1 GB~4.2 GB
500~1.7 GB~5.2 GB~10.5 GB

1.5 Overhead de infraestructura (fijo por servidor)

Metricas internas de VM + Django + Health (con intervalos optimizados a 60s):

FuenteSeriesIntervalo30 dias180 dias
VM self~1,48460s~62 MB~375 MB
Django~51960s~22 MB~133 MB
Health~730s~600 KB~3.5 MB
Total infra~85 MB~512 MB

1.6 Retencion configurada

# compose.observability.yml
- "--retentionPeriod=180d"

VM elimina automaticamente datos mas antiguos de 180 dias. El almacenamiento se estabiliza tras los primeros 180 dias.

1.7 Step de consulta (resolucion de graficas)

El MetricsReader._calculate_step() adapta la resolucion de las queries segun el rango temporal:

RangoStepPuntos aprox.Caso de uso
< 1 hora5s~720Refresh en vivo (5-20s)
1-6 horas15s~1,440Rangos horarios
6-24 horas2m~720Vista diaria
1-3 dias5m~864-2,160Analisis multi-dia
3-7 dias15m~672-1,344Tendencia semanal
7-30 dias30m~1,440Tendencia mensual
30-90 dias2h~1,080Analisis trimestral
> 90 dias4h~1,080Tendencia largo plazo

2. Consumo Total por Tenant

2.1 Desglose por componente

Para un tenant tipico con 100 dispositivos y 180 dias de retencion:

ComponenteAlmacenamiento
VM metricas monitoreo~2.1 GB
PostgreSQL (racks, devices, blueprints, configs, backups)~200 MB
Uploads (logos, stencils, exports)~200 MB
Total por tenant~2.5 GB

2.2 Overhead fijo del servidor (compartido entre todos los tenants)

ComponenteTamano
Docker images (VM, PostgreSQL, Valkey, Django)~4.5 GB
Sistema operativo + herramientas~5 GB
VM metricas infraestructura (180d)~512 MB
Logs (con rotacion)~2 GB
Total fijo~12 GB

3. Planificacion por Tier de Servidor (Hetzner)

3.1 Distribucion de RAM por servicio

ServicioRAM basePor tenant activo
PostgreSQL (shared_buffers)4-16 GB~5 MB
VictoriaMetrics4-16 GB~2 MB (por 700 series)
Valkey (cache sesiones + metricas)1-4 GB~1 MB
Django/Daphne (ASGI workers)2-4 GB base~10 MB por WebSocket concurrente
Sistema operativo2 GB—

3.2 Capacidad por tier

RAM servidorTenantsDevices totalesUsuarios concurrentesDisco usado (180d)
64 GB200-30020-30K~50~750 GB
128 GB500-70050-70K~120~1.75 TB
256 GB1,000-1,500100-150K~250~3.75 TB

Nota: Con 20 TB de disco, incluso el tier mas grande usa menos del 20% del almacenamiento. El disco nunca sera el cuello de botella.

3.3 Cuellos de botella por recurso

RecursoQue lo estresaCuando se nota
RAMSeries en VM + conexiones PostgreSQL + WebSocketsMuchos tenants con Observatory abierto
CPUPings/SNMP/HTTP concurrentes, queries VMMonitoreo desde servidor (sin Local Agent)
RedWebSocket persistente por agent + scrapingMuchos Local Agents conectados
Disco I/OEscrituras VM + WAL PostgreSQLPicos de escritura concurrente

3.4 Factores que alivian carga

  • Local Agent: Ejecuta ping/SNMP/HTTP desde el cliente, no desde el servidor. El servidor solo recibe resultados via WebSocket/API (trafico ligero). Esto reduce drasticamente el consumo de CPU y red.
  • Valkey cache: TTLs adaptativos (5s-30s) para queries VM repetidas. Refreshes consecutivos del Observatory no golpean a VM.
  • Fire-and-forget writes: Las escrituras a VM no bloquean las respuestas HTTP al usuario.

4. Recomendacion de Arranque

Servidor inicial recomendado

Un Hetzner AX42 o similar:

  • 64 GB RAM
  • 2x NVMe (1-2 TB)
  • CPU moderna (Ryzen/Xeon)

Capacidad: 200-300 clientes con 100 devices cada uno.

Escalado futuro

Antes de saltar a un servidor mas grande, separar servicios:

Fase 1 (monolito):
  [Servidor unico] → Django + PostgreSQL + VM + Valkey

Fase 2 (separacion DB):
  [Servidor App] → Django + Valkey
  [Servidor DB]  → PostgreSQL + VictoriaMetrics

Fase 3 (microservicios):
  [App Server(s)]    → Django + Daphne (escalado horizontal)
  [DB Server]        → PostgreSQL (replicacion read-replica)
  [Metrics Server]   → VictoriaMetrics cluster mode
  [Cache Server]     → Valkey Cluster

Cada fase multiplica la capacidad sin reescribir codigo, solo reconfigurando docker-compose y variables de entorno.


5. Arquitectura Multi-Tenant

5.1 Opciones de arquitectura

Opcion A: Stack compartido (arquitectura actual)

┌─────────────────────────────────────────┐
│              1 Servidor                 │
│                                         │
│  ┌─────────┐  ┌─────────┐  ┌────────┐   │
│  │ Django  │  │ Postgre │  │ Victor │   │
│  │ Daphne  │  │  SQL    │  │ Metrics│   │
│  │ (1 inst)│  │(1 inst) │  │(1 inst)│   │
│  └─────────┘  └─────────┘  └────────┘   │
│       ↕            ↕            ↕       │
│   N tenants comparten todo              │
│   Aislamiento: organization FK          │
│                + tenant_id label (VM)   │
└─────────────────────────────────────────┘
AspectoValoracion
A favorSimple, barato, ya implementado. Una sola actualizacion afecta a todos. Maxima eficiencia de recursos.
En contraNoisy neighbor (un tenant pesado afecta a todos). Un bug podria filtrar datos entre tenants. Migraciones de DB afectan a todos simultaneamente.
Ideal paraSaaS joven, <100 tenants, presupuesto ajustado

Opcion B: Stack compartido + Schema por tenant

┌─────────────────────────────────────────┐
│              1 Servidor                 │
│                                         │
│  ┌─────────┐  ┌─────────────────────┐   │
│  │ Django  │  │ PostgreSQL          │   │
│  │ Daphne  │  │  ├─ schema_tenant1  │   │
│  │ 1 inst) │  │  ├─ schema_tenant2  │   │
│  │ +routing│  │  ├─ schema_tenant3  │   │
│  └─────────┘  │  └─ ...×N           │   │
│       ↕       └─────────────────────┘   │
│  ┌─────────┐  ┌────────┐                │
│  │ Valkey  │  │ Victor │                │
│  │(1 inst) │  │ Metrics│                │
│  └─────────┘  └────────┘                │
└─────────────────────────────────────────┘
AspectoValoracion
A favorAislamiento real a nivel DB. Backup/restore individual por tenant. Posibilidad de migrar un tenant a otro servidor sin tocar los demas.
En contraRequiere django-tenants. Mas conexiones DB (1 pool por schema). Mas complejidad operativa.
Ideal paraSaaS medio, clientes enterprise que exigen aislamiento contractual de datos

Opcion C: Stack completo por tenant

┌──────────────────────────────────────────┐
│              1 Servidor                  │
│                                          │
│  ┌─────────────────┐ ┌─────────────────┐ │
│  │ Tenant 1        │ │ Tenant 2        │ │
│  │ Django + DB     │ │ Django + DB     │ │
│  │ + VM + Valkey   │ │ + VM + Valkey   │ │
│  │ (port 8001)     │ │ (port 8002)     │ │
│  └─────────────────┘ └─────────────────┘ │
│  ... × N stacks completos                │
│  RAM: N × ~1.2 GB base = overhead masivo │
└──────────────────────────────────────────┘
AspectoValoracion
A favorAislamiento total. Cada cliente es independiente. Puedes dar versiones diferentes a cada uno.
En contraN instancias de PostgreSQL + VM + Valkey + Django = desperdicio masivo de RAM. Pesadilla de deployments. Costosisimo.
Ideal paraOn-premise / enterprise dedicado, no SaaS

5.2 Arquitectura recomendada

Opcion A reforzada es la correcta para CreaRack Pro porque:

  1. Ya implementado: organization FK en los 12 modelos, tenant_id en VM
  2. 50 tenants es escala pequena-media: PostgreSQL maneja esto sin problemas
  3. 25,000 devices × 7 metricas = 175,000 series: carga moderada para VM
  4. Coste: un solo servidor vs N stacks

Estado actual del aislamiento en el codigo:

MecanismoDondeCantidad
organization FK en modelos*/models.py12 modelos
get_current_org() en views/APIs*/api.py, */views.py210 usos en 18 archivos
tenant_id label en VMMetricsWriter/ReaderTodas las metricas

5.3 Refuerzos recomendados para Opcion A

RefuerzoQue hacePrioridad
PostgreSQL RLSRow-Level Security: el propio DB impide que un tenant vea datos de otro, incluso si hay bug en DjangoAlta
PgBouncerConnection pooling: evita que muchos tenants concurrentes agoten conexionesMedia
Rate limiting per-tenantYa existe en middleware, ajustar limites por organizacionYa existe
Statement timeoutstatement_timeout en PostgreSQL para evitar queries destructivasMedia
Backup per-tenantExport JSON ya existe (backup_full), programar via cronBaja

5.4 Cuando cambiar de arquitectura

SenalAccion
>200 tenantsAnadir read-replica PostgreSQL
>500 tenants o cliente enterprise exige aislamientoMigrar a Opcion B (django-tenants)
Cliente on-premise con requisitos regulatoriosOpcion C solo para ese cliente
Escalado horizontal del app serverKubernetes + multiples pods Django

5.5 Costes por arquitectura (Hetzner, 50 tenants × 500 devices)

ArquitecturaRAM necesariaServidoresCoste aprox/mes
A (compartido)64 GB1~40-60 EUR
B (schema/tenant)64-128 GB1~40-80 EUR
C (stack/tenant)256+ GB2-3~200-400 EUR

6. Migracion A → B (django-tenants)

6.1 Que es django-tenants

django-tenants usa PostgreSQL schemas para aislar datos por tenant. Cada tenant tiene su propio schema con todas las tablas replicadas. Un schema public compartido aloja datos comunes (planes, dominios, configuracion global).

PostgreSQL
├── public (schema compartido)
│   ├── tenants_tenant          ← registro de cada cliente
│   ├── tenants_domain          ← dominios/subdominios
│   └── (planes, pricing, etc.)
├── tenant_acme (schema tenant 1)
│   ├── racks_rack
│   ├── racks_device
│   ├── monitoring_monitoringtarget
│   └── ... (todas las tablas del tenant)
├── tenant_globex (schema tenant 2)
│   ├── racks_rack
│   └── ...
└── ...

El middleware de django-tenants lee el subdominio (acme.crearack.pro) y ejecuta SET search_path TO tenant_acme en cada request. Todas las queries van automaticamente al schema correcto sin cambiar codigo.

6.2 Esfuerzo de migracion

La migracion no es una reescritura. El FK organization ya garantiza que los datos estan separados logicamente — solo falta aislarlos fisicamente en schemas.

Cambios necesarios

AreaCambioEsfuerzo
Dependenciapip install django-tenants (MIT)5 min
SettingsDATABASE_ENGINE → django_tenants.postgresql_backend10 min
SettingsDefinir SHARED_APPS y TENANT_APPS30 min
Modelo TenantCrear modelo Tenant + Domain (hereda de TenantMixin)1 hora
MiddlewareAnadir django_tenants.middleware.TenantMainMiddleware10 min
URLsConfigurar PUBLIC_SCHEMA_URLCONF para paginas publicas30 min
DNSWildcard *.crearack.pro apuntando al servidor10 min
Migracion de datosScript para: crear schemas, mover datos por organization2-3 horas
TestsVerificar que cada tenant ve solo sus datos1-2 horas

Estimacion total: 1-2 dias de trabajo.

Lo que NO cambia

ComponentePor que no cambia
ModelosSe mantienen exactamente igual. El FK organization pasa a ser defense-in-depth (redundante pero no estorba)
Views/APIsget_current_org() sigue funcionando. El schema ya filtra, pero el FK doble-valida
VictoriaMetricstenant_id label ya aísla. Sin cambios
ValkeySolo anadir prefijo de tenant al cache key (1 linea en settings)
FrontendZero cambios. Las URLs de API son identicas
TemplatesZero cambios
ObservatoryCharts.jsZero cambios

Script de migracion de datos (pseudocodigo)

from django_tenants.utils import schema_context

for org in Organization.objects.all():
    # 1. Crear tenant + schema
    tenant = Tenant(schema_name=f"tenant_{org.id}", name=org.name)
    tenant.save()  # django-tenants crea el schema y ejecuta migrate

    # 2. Mover datos al nuevo schema
    with schema_context(tenant.schema_name):
        for rack in Rack.objects.using('default').filter(organization=org):
            rack.pk = None  # forzar INSERT
            rack.save()
        # Repetir para Device, Blueprint, MonitoringTarget, etc.

    # 3. Crear dominio
    Domain(domain=f"{org.slug}.crearack.pro", tenant=tenant, is_primary=True).save()

6.3 Ventajas post-migracion

VentajaDescripcion
Backup granularpg_dump --schema=tenant_acme → backup de un solo cliente
Restore individualRestaurar un tenant sin afectar a los demas
Migracion de tenantMover un cliente a otro servidor: dump schema + restore
Borrado limpioDROP SCHEMA tenant_acme CASCADE elimina todo el cliente
SeguridadIncluso un SQL injection no puede cruzar schemas
PerformanceTablas mas pequenas por schema = indices mas rapidos

6.4 Consideraciones

AspectoDetalle
Conexiones DBCada schema usa el mismo pool de conexiones (PgBouncer recomendado a partir de ~100 tenants)
Migraciones Djangopython manage.py migrate_schemas aplica migraciones a todos los schemas
Admin DjangoFunciona, pero solo ve datos del tenant del subdominio actual
SuperadminAccede via schema public para gestion cross-tenant

6.5 Ruta de migracion recomendada

Fase actual (Opcion A):
  → Lanzar SaaS, captar primeros 50-100 clientes
  → Validar producto-mercado
  → organization FK es suficiente

Fase 2 (~100-200 clientes o primer enterprise):
  → Instalar django-tenants
  → Migrar datos existentes a schemas
  → 1-2 dias de trabajo, zero downtime posible
  → El codigo de la app NO cambia

Fase 3 (~500+ clientes):
  → Separar PostgreSQL a servidor dedicado
  → PgBouncer obligatorio
  → Read-replicas para queries pesadas

Conclusion: La migracion A→B es de bajo coste y bajo riesgo porque el codigo actual ya esta preparado (organization FK en los 12 modelos, get_current_org en 210 puntos). Solo se anade la capa de routing de schemas — no hay que reescribir logica de negocio.


7. Migracion entre Servidores

7.1 Que se migra

Todo el stack corre en Docker con volumenes nombrados. Migrar a un servidor mas capaz es copiar datos y levantar contenedores.

ComponenteComo se migraTamano tipico
Codigo Djangogit clone en el nuevo servidor~50 MB
PostgreSQLpg_dump → pg_restore (o copiar volumen Docker)1-10 GB
VictoriaMetricsCopiar volumen Docker via rsync (archivos planos)1-15 GB
ValkeyNo se migra — es cache, se regenera automaticamente0
UploadsCopiar directorio static/uploads/Variable
.envCopiar manualmente1 KB

7.2 Procedimiento (near-zero downtime)

 1. Levantar nuevo servidor Hetzner                          (30 min)
 2. Instalar Docker + git clone del repo                     (10 min)
 3. Copiar .env + static/uploads/                            (5 min)
 4. pg_dump en origen → pg_restore en destino                (10-30 min)
 5. Copiar volumen VictoriaMetrics via rsync                 (10-60 min)
 6. docker compose up -d en nuevo servidor                   (2 min)
 7. Verificar que todo funciona                              (10 min)
 8. Cambiar DNS al nuevo IP                                  (propagacion: 5-60 min)
 9. Apagar servidor antiguo

Tiempo total: 1-2 horas. Downtime real: solo la propagacion DNS (minutos si se configura TTL bajo previamente).

7.3 Comandos clave

# En servidor ORIGEN — exportar datos
pg_dump -U crearack -h localhost -F c crearack_db > /tmp/db_backup.dump
rsync -avz /var/lib/docker/volumes/victoriametrics_data/ nuevo-server:/tmp/vm_data/

# En servidor DESTINO — importar datos
pg_restore -U crearack -h localhost -d crearack_db /tmp/db_backup.dump
docker volume create victoriametrics_data
rsync -avz /tmp/vm_data/ /var/lib/docker/volumes/victoriametrics_data/_data/
docker compose up -d

7.4 Hetzner: upgrade in-place

Hetzner ofrece upgrade de hardware sin cambiar servidor en algunos planes dedicados (mas RAM, mejor CPU). En ese caso:

  • Se solicita via panel de Hetzner
  • Downtime: solo el reinicio del servidor (~5 minutos)
  • No hay migracion de datos (los discos no cambian)
  • Los contenedores Docker arrancan automaticamente (restart: unless-stopped)

7.5 Estrategia de TTL para migraciones con DNS

Para minimizar downtime durante migraciones entre servidores:

  1. 1 semana antes: Bajar el TTL del DNS de 3600s (1h) a 60s (1min)
  2. Dia de migracion: Cambiar IP en DNS. Propagacion en ~1-2 minutos
  3. Despues de verificar: Subir TTL de vuelta a 3600s

8. Datos Reales de Referencia (06-02-2026)

Medido en entorno de desarrollo con 3 targets activos y ~2 dias de datos:

MetricaValor
Almacenamiento VM total100.6 MB
Series totales2,746
Series monitoreo CreaRack14 (3 targets × 4-5 metricas)
Series infra (VM + Django)~2,732
Directorio data VM9.2 MB

Mantenido por: Equipo CreaRack

Véase también

  • [[crearack-tech—backend—network-observatory]] — backend del Network Observatory
  • [[crearack-tech—architecture—realtime-monitoring-plan]] — plan de monitoring en tiempo real
  • [[crearack-tech—architecture—saas-metrics-architecture]] — arquitectura de métricas SaaS
  • [[crearack-tech—guides—production-deployment]] — deploy en producción Hetzner
  • [[crearack-tech—architecture—valkey-persistence]] — persistencia de Valkey
  • [[crearack-tech—reports—infrastructure-robustness-audit-04-04-2026]] — auditoría de robustez infra