Despliegue a producción sin miedo: build once, canary y rollback real

El deploy que te deja dormir es el que puedes deshacer. Pipeline completo de producción real: build once, canary que prueba de verdad y rollback como parte del diseño.

Publicado 30 Sep 2026·Actualizado 16 Sep 2026·9 min de lectura·Tecnología y Desarrollo
En este artículo

    El mejor despliegue del año no fue el más rápido ni el más elegante: fue el que pudimos deshacer en noventa segundos sin que nadie fuera testigo. El miedo a desplegar no se cura con valentía — se cura con reversibilidad.


    El miedo a desplegar es un problema de diseño

    “No hagan deploy los viernes” es el síntoma; la enfermedad es desplegar sin red de seguridad. Cuando un release no se puede revertir limpiamente, cada despliegue es una apuesta con la producción en la mesa — y el equipo lo sabe, por eso lo aplaza, lo acompaña de madrugada y lo suda. Nosotros desplegamos 300 integraciones acumuladas de un tirón a tres superficies distintas en un día laboral, y esa noche dormimos igual. No fue coraje: fue que cada paso del pipeline existía para eliminar una clase específica de susto.

    Este es el pipeline completo, pieza por pieza, con los números reales del release.

    1. Build selladoimagen inmutable 2. Canarypuerto aparte 3. Journeylogin+ventas+export 4. Swapuna sola operación 5. Verificaciónhealth + rutas 200 6. Rollback listose conserva, no se borra si el journey o la verificación fallan: no se hace swap — y si falla después, el paso 6 ya estaba listo
    El pipeline de seis pasos. Cada paso existe para eliminar una clase de fallo: el sellado elimina el “en mi máquina sí funciona”, el canary elimina el estreno en producción, el rollback elimina el pánico.

    Build, release, run: la separación que lo cambia todo

    La fundación conceptual viene de The Twelve-Factor App, que describe la separación sin dejar lugar a ambigüedad:

    A codebase is transformed into a (non-development) deploy through three stages: The build stage is a transform which converts a code repo into an executable bundle known as a build.

    — The Twelve-Factor App, “Build, release, run”

    Esas tres etapas — build (el repo se transforma en paquete ejecutable), release (el paquete se combina con la configuración y queda sellado, inmutable, versionado) y run (el release se ejecuta) — tienen una consecuencia práctica que lo cambia todo: si quieres cambiar algo en producción, no “editas el servidor” — produces un release nuevo. Cada despliegue es un artefacto identificable al que puedes volver.

    Sin esa separación, “deploy” es un verbo vago que significa acumular cambios en vivo, y el rollback es imposible porque no existe el punto al que volver.

    Ingeniera contemplando una esfera de contenedores brillantes suspendida sobre un puerto nocturno de cargueros
    Build once: el artefacto se construye una vez y viaja sellado. Lo que llega a producción es exactamente lo que probaste — o no es lo mismo.

    Una imagen, tres superficies: build-once mata una clase de bugs

    Nuestro release se desplegó a tres superficies: la producción local en red, una VM remota en la nube y un staging serverless. La regla que lo amarró todo: una sola imagen de contenedor inmutable, construida una vez, promovida idéntica a las tres. La verificación no fue “confía, es la misma”: fue un hash criptográfico. El artifact de 94MB tiene su SHA-256 calculado al construirse, y ese hash se verificó antes y después de cada transferencia; el ID de imagen es literalmente el mismo en local y en la nube.

    ¿Por qué es tan importante? Porque elimina de raíz una familia entera de fallos: “en staging funcionaba”. Cuando cada entorno compila su propia versión, cada build es una ruleta — versiones de dependencias que se mueven, caches que envenenan, flags que difieren. Con build-once, si el canary pasó, lo que llega a producción es lo que pasó el canary. No “debería ser”. Es.

    El canary que sí prueba algo: journey autenticado vs ping

    Muchos equipos llaman canary a un health-check: se levanta la versión nueva en un puerto, /health responde 200, se promueve. Eso prueba que el proceso arrancó — y nada más. El canario de mina era un canario; el tuyo también debería arriesgar algo real.

    Nuestro canary corrió en un puerto aparte con la imagen nueva y, antes de tocar producción, ejecutó un journey autenticado completo: iniciar sesión con credenciales reales, recorrer las rutas críticas del producto (listados, analítica, exportación de datos en formato Excel) y verificar que cada una respondiera 200 con contenido válido. Detrás de ese journey había una suite completa de 786 checks en verde y 14 escenarios de aceptación. Solo cuando el journey completo pasó, se ejecutó el swap — una sola operación, con el entorno heredado al completo.

    El patrón tiene nombre propio en la literatura: los canary releases de Martin Fowler — routear una porción mínima de realidad hacia la versión nueva antes del corte total. La clave que aprendimos: la porción de realidad tiene que incluir estado (sesión, datos, permisos), porque los fallos de producción reales casi nunca viven en la página de inicio que responde 200.

    Rollback como feature: qué conservar y hasta cuándo

    La regla que más paz nos ha dado: el release anterior no se borra el día del lanzamiento — se conserva hasta que la nueva versión demuestre estabilidad extendida. En este release, el contenedor de la versión anterior quedó etiquetado y disponible en las dos superficies, y las bases de datos se respaldaron en dos ubicaciones distintas, con la integridad de cada backup verificada contra su índice interno antes de dar el release por cerrado. Si algo explotaba el miércoles siguiente, volver atrás era un comando, no una odisea.

    Es la versión modesta del clásico blue-green deployment: dos versiones completas coexistiendo y el corte siendo, esencialmente, mover un puntero. No necesitamos el toolkit completo para nuestro caso — con conservar el artefacto anterior y su camino de vuelta bastó. Lo que no es negociable es la filosofía: el rollback se diseña el martes, no se improvisa el viernes.

    Lo que casi lo rompe todo: el entorno, no el código

    La sorpresa del release no vino del código — vino de la configuración. En un despliegue anterior, la versión nueva se levantó con un entorno parcial y falló en el primer intento de arranque por una variable que nadie recordaba que existiera. La lección quedó tallada: el swap debe heredar el entorno completo de la versión saliente, y el diff de configuración se audita antes que el diff de código. En este release, el despliegue heredó las 27 variables del entorno de un tirón, y el health-check dio 200 en el primer intento.

    El env drift es el fantasma silencioso de los despliegues: nadie lo ve en el código, no aparece en los tests, y solo se manifiesta en producción. Trátalo como lo que es — parte del release — y deja de sorprenderte.

    El historial también es infraestructura: nunca reescribas main

    El release incluyó algo que parece burocracia y es supervivencia: consolidar el repositorio privado con merges sin force-push. El main estaba dividido — historias de git sin relación, un squash antiguo de consolidación, archivos que existían “en el otro lado”. La solución fue un merge explícito de historias no relacionadas, resolviendo a favor de la línea aprobada y empujando con fast-forward puro. ¿El resultado? Un main lineal donde cada commit es citable en una conversación de recuperación: “vuelve al commit X” tiene sentido cuando X existe y no fue pulverizado.

    La regla operativa: el historial de git es la bitácora de lo que pasó; reescribirlo para que se vea bonito es quemar el archivo. El PR que no se pudo mergear antes por historias divergentes se resolvió entendiendo la divergencia — no aplanándola a lo loco. El mismo principio rige nuestras otras piezas de ingeniería: en la optimización de 310 a 92 segundos y en los bugs reales de un modelo local programando, la evidencia medida siempre gana a la intuición.

    Y un epílogo honesto: ese mismo release nos dejó una segunda lección que no es de despliegue sino de base de datos — una consulta que se puso 47 veces más lenta sin que el código tuviera nada que ver. Esa historia completa, con su diagnóstico y receta, está en por qué tu query de PostgreSQL se pone lenta de repente.

    Bitácora luminosa de git flotando sobre un taller nocturno, cada commit una estrella encadenada en una línea de tiempo
    Cada commit es una estrella en la bitácora: la cadena se puede recorrer hacia atrás. Reescribir el historial es soltar los eslabones que necesitarás en la próxima emergencia.

    Checklist de release

    PasoCriterio de salidaFallo típico que elimina
    Build sellado + SHA-256Hash del artifact calculado y registrado“En mi máquina sí funciona”
    Canary en puerto aparteVersión nueva corriendo sin tocar producciónEstrenar código en producción
    Journey autenticadoLogin + rutas críticas + export, todo 200 con datos realesEl health-check verde que no prueba nada
    Backup DB verificadoBackup en dos ubicaciones, índice validado“El backup estaba corrupto”
    Swap con entorno heredadoHealth 200 en primer intentoEnv drift en el arranque
    Rollback en esperaContenedor anterior etiquetado y accesible hasta aceptación extendidaPánico del viernes por la noche
    Push fast-forwardMain lineal, sin force-push, commits citablesHistorial incambiable de hecho

    Preguntas frecuentes

    ¿Qué es build once deploy anywhere?

    Construir el artefacto de despliegue (imagen de contenedor, bundle) una sola vez y promover exactamente ese artefacto por todos los entornos, verificando su integridad con un hash. Elimina la clase de bugs donde cada entorno compila su propia versión y “en staging funcionaba”.

    ¿Cuál es la diferencia entre canary release y blue-green deployment?

    Blue-green mantiene dos entornos completos y mueve todo el tráfico de uno a otro de golpe (el rollback es mover el puntero de vuelta). Canary dirige primero una fracción mínima del tráfico real a la versión nueva y observa antes del corte total. Se combinan bien: canary para validar, blue-green para cortar y volver.

    ¿Cuánto tiempo debo conservar el rollback?

    Lo mínimo sano: hasta que la versión nueva pase un periodo de aceptación extendida — días de operación real con usuarios, no solo el health-check de la primera hora. La respuesta precisa depende de tu cadencia: si deployas diario, conservar el padre inmediato basta; si deployas mensual, conserva más historia.

    ¿Por qué evitar force-push en main?

    Porque el historial es la evidencia de lo que pasó y la referencia de cualquier recuperación. Un commit citable (“vuelve al X”) solo existe si nadie lo pulverizó. Los conflictos de historias divergentes se resuelven con merges explícitos, no reescribiendo el pasado.

    ¿Un health-check 200 no basta como verificación?

    No. Un health-check prueba que el proceso respira. Los fallos reales de producción viven en sesiones, permisos, datos y configuración. Un canary que vale algo ejecuta un journey autenticado contra las rutas críticas del negocio antes de autorizar el swap.

    El conocimiento verdadero trasciende a lo público 🌀

    Continúa explorando Tecnología y Desarrollo con piezas relacionadas y evidencia adicional.

    Ver relacionados
    Escrito por

    Escritor en Freaking JSON. Apasionado por la tecnología, gaming y cultura geek.

    Deja un comentario