Migrar una plataforma en producción a un nuevo stack sin downtime
Cómo migrar una plataforma en producción a un nuevo stack sin downtime: ambos sistemas en paralelo, un flujo a la vez y cada paso reversible.
En esta página · 5 secciones
Puntos clave
- Nunca tengas un día en el que solo exista el sistema nuevo: pasa cada solicitud por un switch que pueda enviarla al stack anterior o al nuevo.
- Migra recorridos de usuario, no capas, para que cada paso se entregue, se mida y se pueda revertir por separado.
- Acuerda las cifras que significan “seguro” antes de que se migre el primer usuario real.
En avanzzada lideré la migración completa de una plataforma que se postula automáticamente a ofertas de empleo en nombre de sus usuarios, llevando toda su arquitectura de un stack legado a uno nuevo mientras la gente seguía usándola todos los días. Detener el producto para hacer el cambio en un fin de semana nunca fue una opción: para sus usuarios, un día perdido significa postulaciones perdidas.
Este post es el enfoque que lo hizo posible. No es específico de esa plataforma. El mismo patrón funciona para pasar de un monolito a servicios, de una app en PHP a Node o Go, o de un frontend antiguo a Next.js, siempre que el producto tenga que seguir funcionando mientras trabajas.
¿Por qué migrar?
Una reescritura rara vez es la respuesta correcta, así que el motivo tiene que ser concreto antes de empezar. Las razones honestas casi siempre son una de estas:
- Cada cambio es lento. Las funcionalidades pequeñas toman semanas porque nadie puede predecir qué van a romper.
- Los releases son riesgosos. Los deploys ocurren pocas veces, de noche, con alguien de guardia.
- La plataforma limita el producto. Lo siguiente que necesita el negocio (escala, nuevas integraciones, una app móvil) es difícil o imposible en el stack actual.
- Nadie quiere trabajar en ella. Contratar y retener ingenieros para un stack desactualizado se vuelve más difícil cada año.
“El código es feo” no está en esa lista. Si el único problema es estético, refactoriza en el lugar. Una migración solo vale la pena cuando el sistema anterior está bloqueando el negocio, y deberías poder explicar cómo, en una frase, a quienes la están pagando.
¿Cómo se ejecutan dos sistemas en paralelo?
La primera decisión es la que hace posible todo lo demás: nunca tengas un día en el que solo exista el sistema nuevo. Cada solicitud pasa por un switch que decide, por usuario, qué stack la atiende. Este es el patrón strangler fig, con un feature flag como switch.
// one switch, per user, reversible without a deploy
const useNew = await flags.isEnabled('new-apply-flow', { userId });
return useNew ? newApi.apply(job, user) : legacyApi.apply(job, user);Ese switch te da tres cosas que no puedes obtener de ninguna otra forma:
- Primero los usuarios internos en el stack nuevo, luego una pequeña parte de usuarios reales, luego todos.
- El mismo tipo de solicitud atendido por ambos sistemas, para poder comparar los resultados.
- Un rollback que es un cambio de flag, no un deploy de emergencia.
El switch tiene un costo. Durante un tiempo ejecutas y pagas dos sistemas, y algunos datos tienen que poder leerse desde ambos. Planea ese periodo de forma explícita: decide dónde vive la fuente de verdad de cada dato, y qué sistema lo escribe, antes de mover cualquier tráfico.
¿Por qué migrar un flujo a la vez?
En lugar de migrar capas (primero la base de datos, luego el backend, luego el frontend), migra recorridos de usuario: el registro, luego la acción principal, luego la facturación, y así sucesivamente. Cada recorrido se migra de punta a punta, se entrega por sí solo y tiene sus propias métricas y su propio rollback.
Las migraciones capa por capa se ven ordenadas en el plan y no entregan nada hasta el final. Cuando llega la última capa, meses de trabajo se enfrentan a usuarios reales de golpe, y si algo sale mal no puedes saber qué capa lo causó.
Las migraciones recorrido por recorrido entregan valor desde el primer flujo, y te enseñan. El primer flujo que migres va a exponer problemas en tu plan: datos que no sabías que existían, integraciones que se comportan distinto, casos borde que nadie documentó. Mejor aprender eso en un flujo que en todos.
Elige el primer flujo con cuidado. Debe ser lo bastante real como para probar el stack nuevo con tráfico de producción, pero no el que más dinero genera. Un recorrido secundario con tráfico constante es ideal.
Una migración es un lanzamiento de producto que se supone que nadie debe notar.
Filipe Eduardo
Medir que nada se rompió
Para cada flujo, acuerda las cifras antes de migrar a cualquier usuario:
- Tasa de éxito de la acción principal (para una plataforma de postulaciones: postulaciones enviadas con éxito).
- Latencia en el percentil 95, comparada entre el sistema anterior y el nuevo para el mismo tipo de solicitud.
- Tasa de errores en el camino nuevo, con una alerta que se dispare antes de que los usuarios se quejen.
Luego mueve el tráfico por etapas (usuarios internos, 5%, 25%, 50%, 100%) y solo avanza cuando las cifras se mantengan el tiempo suficiente como para confiar en ellas. Si no se mantienen, regresa el switch, corrige y vuelve a intentarlo. Nadie fuera del equipo necesita enterarse.
¿Cuánto tarda una migración así?
Depende del número de recorridos, no del tamaño de la base de código. Un flujo pequeño se puede migrar en pocas semanas una vez que existen el switch y el monitoreo; una plataforma completa suele tomar meses. El primer flujo siempre es el más lento, porque paga la infraestructura que reutilizan todos los flujos siguientes: el switch, los dashboards, la sincronización de datos.
Dos cosas acortan el plazo más que cualquier otra: congelar las funcionalidades nuevas en el stack anterior (el trabajo nuevo va solo al stack nuevo) y borrar el código antiguo en cuanto un flujo llega al 100%. Cada semana que las dos versiones de un flujo siguen vivas, pagas por mantener ambas.
¿Qué volvería a hacer?
Si tuviera que reducir el enfoque a tres reglas:
- Pon un switch delante de todo antes de escribir código nuevo.
- Migra recorridos, no capas.
- Acuerda las cifras que significan “seguro” antes de que se migre el primer usuario.
El resto es disciplina: avanzar en pasos pequeños, vigilar las cifras y resistir la tentación de “simplemente pasar a todos” cuando el primer flujo se ve bien.
Preguntas frecuentes
¿Cómo se migra un sistema en producción sin downtime?
Ejecuta el sistema anterior y el nuevo en paralelo detrás de un switch, normalmente un feature flag, y mueve el tráfico al stack nuevo de forma gradual. Compara la tasa de éxito, la latencia y los errores para el mismo tipo de solicitud, y haz rollback cambiando el flag en lugar de hacer un deploy. Los usuarios nunca ven un cambio de sistema, porque no lo hay.
¿Conviene migrar por capas o por funcionalidades?
Por funcionalidad, o por recorrido de usuario. Migrar un recorrido de punta a punta te permite entregar, medir y revertir cada paso de forma independiente, y aprendes del primer flujo antes de migrar el resto. Las migraciones capa por capa solo entregan valor al final, cuando todos los cambios se enfrentan a usuarios reales de golpe.
¿Qué se debe medir durante una migración?
Las cifras que sienten los usuarios: la tasa de éxito de la acción principal, la latencia en el percentil 95 y la tasa de errores, comparadas entre el stack anterior y el nuevo para el mismo tráfico. Acuerda los umbrales que significan “seguro” antes de migrar a nadie, y solo avanza a la siguiente etapa de tráfico cuando se mantengan.
