commit&push

~/blog $ git show 2026-09-03

Merge Is Not Deploy

· 3 min read · Victor Benavides

--ops--craft

El martes por la mañana, el post más nuevo de este blog estaba integrado y devolvía un 404 al mismo tiempo.

No era un bug. El pull request estaba aprobado e integrado, la rama ya no existía, el commit estaba en la rama de desarrollo — y el post no existía en internet, porque lo que publica de verdad es una promoción a otra rama, y nadie la había ejecutado todavía.

Integrado. No desplegado. Dos estados, y yo los venía tratando como uno solo.

INTEGRADOen la ramaDESPLEGADOcorriendo en prodVERIFICADOcomprobado — y cómoun workflow verde no es un pod corriendoun pod corriendo no es una función usablela palabra que esconde todo esto: "listo"
Tres estados, dos brechas. Casi todas las respuestas equivocadas a “¿esto está en producción?” vienen de colapsar los tres en una sola palabra, y el colapso es invisible hasta que alguien te pide certeza.

La primera brecha

Un merge pone código en una rama. Eso es todo lo que hace.

Entre ahí y producción hay un despliegue, y un despliegue es un evento aparte que puede simplemente no ocurrir. El workflow no se disparó porque el push vino de un token de automatización. La promoción necesitaba a un humano y el humano estaba respondiendo otra pregunta. El build salió en verde y publicó un artefacto que nunca se puso en circulación.

Cada una de esas situaciones te deja con un check verde y una producción sin cambios. El check está diciendo la verdad — simplemente no está respondiendo la pregunta que le estás haciendo.

La segunda brecha

La que la gente se salta es peor, porque parece terminada.

Un pod puede estar corriendo y devolviendo errores. Un servicio puede desplegarse perfectamente con un valor de configuración que necesita todavía ausente. Una función puede estar completamente desplegada y apagada detrás de un flag — lo cual muchas veces es deliberado, y aun así significa que la respuesta a "¿alguien puede usarla?" es no.

Desplegado significa que el código está ahí. No significa que el comportamiento esté ahí. Esas dos cosas se separan constantemente, y se separan en silencio, porque nada en tus herramientas está diseñado para notar la diferencia.

Por qué cuesta algo

Colapsar todo esto en "listo" no duele hasta que alguien te pide certeza.

Ahí te descubres diciendo que estás bastante seguro de que algo está en producción — y construyendo encima de eso, o asumiendo que una protección está encendida, o reconstruyendo algo que ya se había desplegado. La falla no es dramática. Es una decisión tomada sobre un estado que nunca comprobaste.

Lo que lo arregla es aburrido

Dale nombre a los estados intermedios y deja que sean respuestas válidas.

"Construido, no desplegado" es un estado. "Solo en dev" es un estado. Ninguno de los dos es un fracaso ni una excusa — simplemente son ciertos, y tener las palabras disponibles te evita redondearlo todo hacia "listo".

Después haz una sola regla: algo está en producción cuando se comprobó contra producción, con una nota de cómo se comprobó. No integrado. No desplegado. Comprobado. Una URL que cargaste, una petición que hiciste, una fila que viste.

El blog que estás leyendo se publica cuando corre una promoción, y sé que está vivo porque le pedí la página a producción y producción me la dio. Ese listón es más bajo de lo que suena, y aun así está más alto del que superamos casi todos.

$ grep -rl --tag ~/blog