Módulo 1: From Experiment To Launch

Deployar no es lo mismo que lanzar

Descripción

La lección 4 mostró que controlar el radio de impacto —exponer al 1% en vez del 100%— es la palanca más poderosa contra un daño conocido. Pero esa palanca solo existe si el código en producción y la exposición a los usuarios son dos cosas separadas. Esta lección nombra esa separación: deploy es el momento en que el código llega a los servidores de producción; release es el momento en que un usuario real, cualquiera, empieza a interactuar con él. Son dos eventos distintos, y confundirlos es uno de los hábitos de lenguaje más comunes —y más costosos— en un equipo de producto.

Conexión con el módulo. Esta lección no enseña cómo se logra técnicamente esa separación —eso es exactamente lo que el módulo 2 hace con feature flags—; enseña por qué la separación importa, como preparación conceptual antes de tocar la herramienta. Es la pieza que le faltaba al radio de impacto de la lección 4: sin distinguir deploy de release, "exponer solo al 1%" no tiene ningún mecanismo posible detrás.

Una analogía: la obra terminada, antes de la inauguración

Un restaurante nuevo puede tener la cocina lista, el menú impreso, el personal contratado y entrenado, las mesas puestas — todo, literalmente, en su lugar y funcionando — semanas antes de abrir las puertas al público. Ese estado, "listo pero cerrado", es exactamente lo que el equipo necesita para hacer los últimos ajustes con calma: probar platillos con el personal, corregir el flujo de la cocina, sin la presión de comensales reales sentados en las mesas. El día de la inauguración, el dueño no reconstruye el restaurante — simplemente abre la puerta de un lugar que ya estaba, en todo sentido práctico, terminado.

"El restaurante está listo" (deploy) y "el restaurante está recibiendo comensales" (release) son, obviamente, dos momentos distintos para cualquiera que piense en un restaurante. La confusión aparece, casi siempre, solo con el software — porque el hábito de decir "ya lo subimos" (deploy) se usa, sin querer, como sinónimo de "ya lo lanzamos" (release), cuando en realidad son la cocina lista y la puerta abierta: dos eventos que pueden pasar el mismo día, o con semanas de diferencia, según decida el equipo.

Ejemplo trabajado: launchState() a lo largo de la línea de tiempo de recommendations

Vamos a nombrar, con precisión, los distintos momentos por los que pasa recommendations entre que el código se escribe y que el 100% de Mercado lo usa. El modelo distingue dos preguntas: ¿el código está en producción? y ¿qué porcentaje de usuarios realmente lo ve?

// launchState: nombra el momento exacto de un cambio, distinguiendo "esta en
// produccion" (deployed) de "los usuarios lo ven" (released). El COMO se logra
// esa separacion -- feature flags -- es el modulo 2; aqui solo se nombra la
// diferencia.
function launchState({ inProduction, percentSeeingIt }) {
  if (!inProduction) return 'no deployado';
  if (percentSeeingIt === 0) return 'deployado, no released (nadie lo ve todavia)';
  if (percentSeeingIt < 100) return 'deployado, released parcialmente (' + percentSeeingIt + '% lo ve)';
  return 'deployado y released por completo (100%)';
}

const recommendationsTimeline = [
  { moment: 'codigo mergeado, antes del primer deploy', inProduction: false, percentSeeingIt: 0 },
  { moment: 'deploy a produccion, feature flag apagado', inProduction: true, percentSeeingIt: 0 },
  { moment: 'A/B test (control/variant, ~10% de la base)', inProduction: true, percentSeeingIt: 10 },
  { moment: 'rollout completo (adelanta el modulo 3)', inProduction: true, percentSeeingIt: 100 },
];

console.log('=== launchState a lo largo de la linea de tiempo de recommendations ===\n');
recommendationsTimeline.forEach((t) => {
  console.log(t.moment);
  console.log('  -> ' + launchState(t) + '\n');
});

Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:

=== launchState a lo largo de la linea de tiempo de recommendations ===

codigo mergeado, antes del primer deploy
  -> no deployado

deploy a produccion, feature flag apagado
  -> deployado, no released (nadie lo ve todavia)

A/B test (control/variant, ~10% de la base)
  -> deployado, released parcialmente (10% lo ve)

rollout completo (adelanta el modulo 3)
  -> deployado y released por completo (100%)

Fíjate en la segunda fila: deployado, no released. Ese estado —código corriendo en los servidores de producción de Mercado, funcionando, pasando todas las pruebas de infraestructura, y al mismo tiempo absolutamente ningún usuario viéndolo— es el que el lenguaje cotidiano ("ya lo subimos a producción") tiende a saltarse, tratándolo como si fuera equivalente a la última fila. No lo es. Entre la fila 2 y la fila 4 hay dos decisiones de negocio completas —cuándo empezar el A/B test, cuándo llevarlo a 100%— que no tienen absolutamente nada que ver con si el código "está listo" en el sentido de ingeniería.

Por qué esta distinción es la que hace posible todo lo demás

Vuelve a la lección 4 por un momento: blastRadius() mostraba que exponer al 1% en vez del 100% reduce el daño cien veces. Esa comparación solo es posible porque deploy y release son eventos separables — si "el código está en los servidores" significara automáticamente "el 100% de los usuarios lo ve", no existiría ningún punto intermedio que probar. El radio de impacto controlado de la lección 4, el rollout gradual del módulo 3, el kill switch del módulo 2 — todas esas herramientas dependen, como condición previa, de que alguien haya construido el mecanismo que separa "el código corre" de "el usuario lo experimenta". Esa es la razón de peso de por qué esta distinción, aunque suene casi obvia una vez dicha en voz alta, merece su propia lección: es la base conceptual sin la cual nada del resto de esta guía tendría sentido técnico.

Vale aclarar, para no adelantarse: el mecanismo concreto que logra esta separación en la práctica —un feature flag, con su lógica de isEnabled(user, flag)— es exactamente lo que construye el módulo 2. Aquí solo tienes el vocabulario y el porqué; ahí vas a tener la herramienta.

Errores comunes

Usar "deployado" y "lanzado" como sinónimos, en conversaciones que sí importan. Qué pasa: alguien reporta en una reunión "ya está en producción" refiriéndose al deploy, y el resto del equipo lo interpreta como "ya está lanzado" — con consecuencias reales, como planear una comunicación de marketing para una fecha que en realidad solo marca cuándo el código podría encenderse. Por qué pasa: en el habla cotidiana, "está en producción" suena a "está listo para todos", y el matiz de "deployado pero apagado" no siempre se comunica explícitamente. Cómo detectarlo: dos personas en la misma conversación usan "en producción" con significados distintos sin darse cuenta — una lo dice pensando en el código, la otra pensando en los usuarios. Cómo corregirlo: usa siempre los dos términos con precisión — "deployado" para el código en los servidores, "released" (o "lanzado") para lo que ven los usuarios — y, cuando haya ambigüedad, pregunta explícitamente "¿deployado o lanzado?"

Asumir que, si el código no está deployado, no se puede empezar a construir el plan de lanzamiento. Qué pasa: el equipo espera hasta el día del deploy para empezar a pensar en el rollout, el monitoreo, y el plan de rollback — como si esas decisiones dependieran de que el código ya estuviera físicamente en producción. Por qué pasa: parece natural planear "lo que sigue" solo después de terminar "lo anterior", en un orden estrictamente secuencial. Cómo detectarlo: el plan de rollout se improvisa el mismo día del deploy, en vez de estar listo de antemano. Cómo corregirlo: como muestra la línea de tiempo del ejemplo, hay un espacio completo —"deployado, no released"— diseñado exactamente para que el equipo prepare con calma el resto del plan (los módulos 3 a 5 de esta guía) antes de exponer a nadie, igual que el restaurante de la analogía ajusta la cocina antes de abrir la puerta.

Tratar cada avance de porcentaje de release como si requiriera un nuevo deploy. Qué pasa: alguien asume que pasar de "10% ve la feature" a "50% ve la feature" implica volver a subir código a producción, con todo el riesgo de infraestructura que eso conlleva (nueva build, nuevo pipeline, nueva ventana de mantenimiento). Por qué pasa: sin haber visto todavía el mecanismo del módulo 2 (feature flags), es fácil imaginar que la única forma de cambiar qué porcentaje ve algo es tocando el código de nuevo. Cómo detectarlo: cada cambio de porcentaje en el plan de rollout aparece en el calendario como "deploy #4", "deploy #5", etc. Cómo corregirlo: recuerda la fila 3 y 4 del ejemplo — el mismo deploy (fila 2) sostiene tanto el 10% como el eventual 100%; lo único que cambia entre esas filas es una configuración, no el código. Ese es, precisamente, el mecanismo que vas a construir en el módulo 2.

Ejercicios

Ejercicio 1 — Clasifica el estado. El equipo de Mercado acaba de hacer deploy de una nueva versión del carrusel de recommendations con un bug corregido, pero decide mantener la exposición al mismo 10% que ya tenía antes del deploy (no la sube ni la baja). ¿Cuál es el launchState() correcto para esta situación?

Ver solución

'deployado, released parcialmente (10% lo ve)' — exactamente el mismo estado que antes del deploy nuevo, porque launchState() solo mira inProduction y percentSeeingIt, no si el código específico cambió. Esto ilustra un punto sutil: un nuevo deploy no cambia automáticamente el estado de release — el equipo decidió, a propósito, mantener el mismo porcentaje mientras el código nuevo (con el fix) reemplaza al viejo detrás del mismo flag. Deploy y release son independientes en las dos direcciones: puedes cambiar uno sin tocar el otro.

Ejercicio 2 — Encuentra el error de comunicación. Un ingeniero le dice al equipo de marketing: "recommendations ya está en producción, pueden anunciarlo." Marketing programa un correo a toda la base de usuarios para esa misma tarde. ¿Qué salió mal, usando el vocabulario de esta lección?

Ver solución

El ingeniero usó "está en producción" (deploy) donde marketing necesitaba saber "está released al 100%" — dos afirmaciones distintas que el mensaje trató como si fueran una sola. Si recommendations está deployado pero con el flag apagado (o en un rollout parcial al 10%), el correo de marketing va a generar tráfico hacia una feature que la mayoría de los destinatarios ni siquiera puede ver. La corrección: cualquier comunicación entre equipos sobre el estado de un lanzamiento debería especificar cuál de los dos eventos —deploy o release, y en el caso de release, qué porcentaje— está confirmando.

Ejercicio 3 — Explica el valor de la fila 2. Sin usar la palabra "flexibilidad", explica en dos o tres frases por qué el estado "deployado, no released" —código en producción, cero usuarios viéndolo— es valioso, y no simplemente un paso de trámite entre escribir código y lanzarlo.

Ver solución

Ese estado le da al equipo la oportunidad de verificar que el código se comporta bien en el entorno real de producción —con la configuración real, la infraestructura real, los datos reales— sin que ningún usuario esté expuesto a lo que encuentren. Es, literalmente, la diferencia entre descubrir un problema con cero usuarios afectados y descubrirlo con usuarios reales ya en medio de una experiencia rota. También separa por completo la decisión técnica ("¿el código funciona?") de la decisión de negocio ("¿es el momento correcto para que la gente lo vea?") — permitiendo, por ejemplo, tener el código listo con semanas de anticipación y decidir el momento exacto del lanzamiento por razones de negocio (una fecha de campaña, la disponibilidad del equipo de soporte) sin ninguna presión técnica de por medio.

Resumen y siguiente paso

En esta lección nombraste con precisión dos momentos que el lenguaje cotidiano confunde: deploy (el código está en los servidores de producción) y release (los usuarios reales interactúan con él). Con launchState() trazaste la línea de tiempo completa de recommendations, desde "no deployado" hasta "deployado y released por completo", pasando por el estado intermedio —deployado, sin nadie viéndolo todavía— que hace posible todo el resto de esta guía: sin esa separación, controlar el radio de impacto de la lección 4 sería, simplemente, imposible.

Antes de avanzar deberías poder: explicar la diferencia entre deploy y release con tus propias palabras; identificar, dado un estado de un lanzamiento, si es deploy sin release, release parcial, o release completo; y explicar por qué esta separación es la condición previa de la que depende el radio de impacto controlado.

La lección 6 sube un nivel de abstracción: en vez de mirar una pieza a la vez (radio de impacto, deploy vs. release), va a sintetizar qué tienen en común, estructuralmente, todos los lanzamientos cuidadosos — un patrón de tres propiedades que vas a reconocer en cada herramienta concreta de los módulos 2 a 5.

Recursos

  • Charity Majors, "Deploys Are the WRONG Way to Change User Experience" — honeycomb.io/blog/deploys-wrong-way-change-user-experience. El artículo que desarrolla a fondo la distinción de esta lección: "deploy es el proceso de construir, probar y llevar cambios a producción; release es el proceso de cambiar la experiencia del usuario de forma significativa". En inglés.
  • Pete Hodgson (con Martin Fowler), "Feature Toggles (aka Feature Flags)" — martinfowler.com/articles/feature-toggles.html. El mecanismo técnico que hace posible, en la práctica, la separación entre deploy y release nombrada hoy — desarrollado a fondo en el módulo 2 de esta guía. En inglés.