Plan de Migración · NutriTrack SaaS B2B
PostgreSQL 13 On-Premises CPD Madrid → PostgreSQL 15 AWS RDS eu-west-1
ID: 5ff113ab9ed0 Complejidad: Alta 60h estimadas GDPR
🗄️
48 GB
Datos a migrar
⏱️
15 min
Downtime máx (SLA)
📋
5
Fases de migración
⚠️
6
Riesgos identificados
🔄
4
Issues compatibilidad
🛡️
5 min
RTO Rollback
🗺️ Fases de Migración — Patrón Expand-Contract
Zero-Downtime
1
Preparación
Backups completos, configuración de monitoreo, briefing de equipo, validación de prerequisites
12h
duración
Riesgo: Medio
🔒 Backup PostgreSQL 13 📊 Setup CloudWatch 📋 Rollback testing 📢 Notificación stakeholders ✅ Validar prerequisites
Backups completados y verificados (checksums)
Sistemas de monitoreo operacionales
Procedimientos de rollback testeados
Equipo briefeado y disponible
2
Expand — Esquema Dual
Añadir nuevas columnas y constraints SIN eliminar las existentes. app-menus y worker-pedidos usan ambas versiones
12h
duración
Riesgo: Medio
➕ ADD COLUMN allergen_code jsonb 📝 ALTER COLUMN descripcion → text 🔗 CREATE INDEX CONCURRENTLY GIN ⚙️ Feature flags habilitados
DDL aplicado sin bloqueos (LOCK TIMEOUT = 1s)
Índice GIN creado CONCURRENTLY (sin downtime)
Tests de integración api-menus verdes
3
Migración — Replicación CDC
Change Data Capture con pglogical: replicación continua on-prem → RDS durante la ventana 03:00–06:00 UTC
12h
duración
Riesgo: Alto
🔄 pglogical streaming ✅ Row count validation 🔐 Checksum por tabla ⚡ Canary 5% → 25% → 50% 📈 Baseline p95 < 80ms
Row counts iguales en source y target (tolerancia 0)
p95 query time < 80ms en RDS bajo carga canary
worker-pedidos procesando en target sin errores
4
Contract — Cutover Total
100% tráfico a RDS. Ventana de mantenimiento 5 min para apuntar DNS y reiniciar servicios
12h
duración
Riesgo: Medio
🌐 DNS cutover (TTL 30s) 🔌 api-menus → RDS endpoint 🛑 Parar pglogical 📊 Monitor 72h post-cutover
0 errores en logs de api-menus tras cutover
constraint precio_positivo_check funcional
Búsquedas allergen_code < 10ms (índice GIN)
5
Limpieza — Decommission
Retiro del servidor on-premises CPD Madrid tras 72h de observación estable en producción RDS
12h
duración
Riesgo: Bajo
🗄️ Archivar backup final on-prem 📦 Decommission servidor físico 📝 Actualizar documentación 🔍 Post-mortem review
Cambios de Esquema — NutriTrack DB
Tabla Tipo Detalle
ingredientes + columna allergen_code jsonb NULL
ingredientes constraint precio_unitario > 0
ingredientes índice GIN idx_allergen_gin (allergen_code)
menus modify descripcion: varchar(500) → text
Tablas a Migrar — Volumen por tabla
menus
Filas850K
Tamaño320 MB
Crítica
ingredientes
Filas1.2M
Tamaño480 MB
Crítica
pedidos
Filas2M
Tamaño960 MB
Crítica
usuarios
Filas15K
Tamaño8 MB
Crítica
reportes_nut...
Filas500K
Tamaño200 MB
Normal
audit_logs
Filas8M
Tamaño1.8 GB
Normal
🔍 Análisis de Compatibilidad — compatibility_checker.py
Potentially Incompatible
4
issues
⚠ Potentially Incompatible
0 breaking changes
4 potentially breaking
Requieren validación manual
0 Breaking 4 Pot. Breaking 0 Non-Breaking
⚠️
CHECK constraint en user_sessions
Nuevo constraint: session_type IN ('web', 'mobile', 'api', 'admin') — puede rechazar datos existentes con otros valores
→ Validar: SELECT count(*) FROM user_sessions WHERE session_type NOT IN ('web','mobile','api','admin'); antes de aplicar
Pot. Breaking
⚠️
CHECK constraint en users.phone
Constraint: phone IS NULL OR LENGTH(phone) >= 10 — teléfonos cortos/legacy serán rechazados
→ Limpiar datos: UPDATE users SET phone = NULL WHERE LENGTH(phone) < 10;
Pot. Breaking
⚠️
CHECK constraint user_profiles.language
Lista permitida: en, es, fr, de, it, pt, ru, ja, ko, zh — idiomas no listados serán rechazados
→ Normalizar: mapear códigos legacy a equivalentes permitidos antes del cutover
Pot. Breaking
⚠️
CHECK constraint user_profiles.bio
Máx 2000 chars en campo bio — registros existentes con bio > 2000 chars serán rechazados al actualizar
→ Truncar: UPDATE user_profiles SET bio = LEFT(bio, 2000) WHERE LENGTH(bio) > 2000;
Pot. Breaking
Matriz de Riesgos — 6 Riesgos Identificados
Categoría Riesgo Prob. Impacto Owner
⚙ Operacional Rollback no testeado en staging Alta Crítico QA Team
💼 Negocio Zero-downtime aumenta complejidad Alta Medio DevOps
⚡ Técnico Downtime extendido Media Alto DevOps
💼 Negocio Disrupción de procesos Media Alto Biz Owner
✅ Compliance Requisitos GDPR en migración Media Alto Legal
⚡ Técnico Corrupción de datos Baja Crítico DBA Team
Runbook de Rollback — rollback_generator.py
Triggers Automáticos
Error rate > baseline × 5 durante 5 min
AUTO
Availability < 95% durante 2 min
AUTO
p95 response time > baseline × 3 (10 min)
MANUAL
Data integrity check failure
AUTO
Matriz de Decisión
Baja severidad Continuar con monitoreo
Severidad media Evaluar y decidir en 15 min
Severidad alta Rollback inmediato
Crítica / Data loss Emergency — all hands
🏗️ Patrones de Migración Aplicados
📖
Expand-Contract
Patrón principal para cambios de esquema sin bloquear la app en producción
1
Expand: añadir allergen_code como nullable
2
Dual write: app escribe en ambos schemas
3
Backfill: poblar histórico allergen_code
4
Contract: activar constraint NOT NULL final
🐤
Canary Deployment
Cutover progresivo de tráfico hacia RDS con validación por lotes
1
5% tráfico a RDS (30 min observación)
2
25% si métricas OK (45 min)
3
50% validación p95 < 80ms
4
100% cutover en ventana 03:00 UTC
🔄
Change Data Capture
Replicación en tiempo real usando pglogical para zero data-loss durante migración
1
Snapshot inicial de tablas críticas
2
pglogical stream: on-prem → RDS
3
Validación de lag < 100ms
4
Detener CDC tras cutover exitoso
⚙️ Pipeline CI/CD — GitHub Actions
Plan
migration_planner.py
--input nutritrack_migration.json
✓ Passed
Compat Check
compatibility_checker.py
--before before.json --after after.json
⚠ 4 Issues
Rollback Gen
rollback_generator.py
--input migration_plan.json
✓ Generated
Staging Test
pg_dump | restore
Run E2E tests
⏳ Pending
Approval Gate
DBA + Biz Owner
sign-off required
⏳ Pending
Production
Execute 03:00 UTC
window
⏳ Scheduled
Gate de aprobación bloqueado: La migración NO puede avanzar hasta que (a) los 4 issues del compatibility checker sean aceptados por escrito por el DBA owner, y (b) exista un rollback runbook validado en staging para cada fase del plan.
📋 Pre-Migration Checklist
6/10 completados
Plan de migración revisado y aprobado
Backup PostgreSQL 13 verificado (checksum)
Monitoreo CloudWatch + Grafana configurado
AWS RDS instance provisionada (db.r6g.xlarge)
pglogical instalado en source y target
Feature flags preparados en api-menus
Rollback procedures testeados en staging
Validación de datos con constraint check
Load test p95 < 80ms en staging RDS
Sign-off DBA + Business Owner
Criterios de Éxito
100% datos migrados con integridad (0 pérdida)
Performance igual o superior al baseline on-prem
Todos los procesos de negocio funcionando
Sin vulnerabilidades de seguridad introducidas
Downtime real ≤ 15 min (SLA contractual)
Documentación y runbooks actualizados