Módulo 5: Rollback And Incident Response
El rollback es tu red de seguridad
Descripción
recommendations ya tiene un kill switch desde el módulo 2: una sola línea, recommendationsFlag.enabled = false, que apaga la exposición para el 100% de los usuarios al instante, sin importar en qué etapa de la rampa estaba el rollout. Esta lección le da un nombre más amplio a esa capacidad, y la pone en el contexto donde de verdad importa: cuando un guardrail se rompe en producción, el kill switch es tu rollback — y es, casi siempre, la opción más rápida disponible.
Conexión con el módulo. La lección 1 dejó abierta la pregunta "¿revertimos o arreglamos hacia adelante?" sin dar todavía ningún criterio para decidir. Esta lección no contesta esa pregunta completa —eso es la lección 3—, pero construye la mitad de la información que hace falta para contestarla: cuánto cuesta, en tiempo, la opción de revertir. Sin ese número, no hay forma de compararlo contra el costo de un fix hacia adelante.
Una analogía: la red del trapecista, no el Ctrl+Z
Es tentador pensar en el rollback como el Ctrl+Z de un editor de texto: deshacer el último cambio y volver exactamente a donde estabas. Esa analogía no está mal del todo, pero le falta una parte importante — un Ctrl+Z deshace un cambio, típicamente el más reciente, y asume que todo lo demás quedó intacto mientras tanto. El rollback de un incidente real es más parecido a la red del trapecista: no evita que el trapecista se resbale del trapecio —el guardrail ya se rompió, eso ya pasó—; lo que hace es evitar que ese resbalón se convierta en una caída al piso que lastime a alguien. La red no rebobina el tiempo hasta antes del resbalón. Atrapa la caída, en el momento en que ocurre, y da tiempo para pensar el siguiente movimiento sin que nadie salga herido mientras tanto.
recommendationsFlag.enabled = false es exactamente esa red. No borra el hecho de que la latencia se rompió durante los minutos u horas en que la feature estuvo expuesta al 10% de la base — ese daño, sobre esos 25,000 usuarios, ya ocurrió. Lo que sí hace es detener, de inmediato, que siga ocurriendo sobre un usuario más. La red no evita la caída. Evita que la caída se convierta en algo peor.
Ejemplo trabajado: cuánto tarda cada forma de "achicar" la exposición
Mercado tiene, en teoría, dos formas de reducir la exposición de recommendations una vez que el guardrail está roto en rollout 10%: apagar el kill switch de un golpe, o "retroceder" la rampa un escalón a la vez, con el mismo cuidado que se usó para subirla. Vamos a medir el costo real de cada una:
// revertLatency: compara dos formas de "achicar" la exposicion de recommendations
// cuando el guardrail se rompe en rollout 10% (M3/M4). killSwitch usa el mismo campo
// `enabled` de M2 L5 -- un booleano, sin importar la etapa. stepDown intentaria bajar
// un escalon de la rampa a la vez, respetando el mismo dwell time minimo (M3 L7) que
// se uso para SUBIR -- un protocolo pensado para avanzar con confianza, no para una
// emergencia.
function revertLatency(mechanism) {
const dwellMinutesAtCurrentStage = 12 * 60; // minDwellHours de "rollout 10%" (M3 proyecto)
if (mechanism === 'killSwitch') return 2; // un booleano, enabled=false, sin importar la etapa
if (mechanism === 'stepDown') return dwellMinutesAtCurrentStage; // esperar el dwell time antes de confiar en el paso atras
throw new Error('mecanismo desconocido: ' + mechanism);
}
console.log('=== revertLatency en rollout 10% (25,000 usuarios expuestos, guardrail roto) ===\n');
['killSwitch', 'stepDown'].forEach((m) => {
const minutes = revertLatency(m);
const label = minutes >= 60 ? (minutes / 60) + 'h' : minutes + 'min';
console.log(m.padEnd(12) + '-> ' + label + ' hasta que ningun usuario ve recommendations');
});
Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:
=== revertLatency en rollout 10% (25,000 usuarios expuestos, guardrail roto) ===
killSwitch -> 2min hasta que ningun usuario ve recommendations
stepDown -> 12h hasta que ningun usuario ve recommendations
La diferencia es enorme, y vale la pena entender de dónde sale. killSwitch tarda 2 minutos porque, como viste en el módulo 2, es literalmente cambiar un valor de true a false — no importa si la rampa estaba en 1% o en 100%, el costo es el mismo. stepDown, en cambio, tarda 12 horas, porque ese número no es arbitrario: es el mismo minDwellHours que el módulo 3 le asignó a la etapa rollout 10% — el tiempo mínimo que hace falta esperar para confiar en que los datos de una etapa son reales, y no ruido. Ese tiempo de espera tiene todo el sentido cuando estás avanzando con cuidado hacia más exposición. No tiene ningún sentido cuando estás intentando salir de una exposición que ya sabes que es dañina — y sin embargo, si tu único mecanismo para reducir el porcentaje es "bajarlo un escalón, esperar, confirmar, bajar otro escalón", terminas atrapado en el mismo protocolo lento diseñado para lo contrario de lo que necesitas en ese momento.
Por qué el kill switch es la red, y no un plan B ocasional
Nota algo importante en el resultado: killSwitch no depende de en qué etapa está la rampa. Si el guardrail se hubiera roto en rollout 50% en vez de rollout 10%, el costo de revertir con el kill switch seguiría siendo 2 minutos — mientras que stepDown habría tardado 24 horas (el minDwellHours de esa etapa, según la tabla del proyecto del módulo 3), no 12. Esa es la propiedad que hace del kill switch una red de seguridad real y no solo una herramienta útil: su costo no crece con el radio de impacto que ya alcanzó el problema. Cuanto más alto sube la rampa, más falta hace una salida que no dependa de la misma cautela que se usó para subir.
Esto no significa que el rollback sea siempre la respuesta correcta — eso es exactamente lo que la lección 3 va a poner a prueba, comparando su costo contra el de un fix hacia adelante—. Significa que, antes de comparar nada, hace falta saber el número real: en esta guía, gracias al feature flag del módulo 2, ese número casi siempre es minutos, no horas.
Errores comunes
Confundir "bajar el porcentaje" con "activar la red de seguridad". Qué pasa: frente a un guardrail roto, alguien reduce rolloutPercent de 10 a 5, pensando que eso es "revertir un poco" — cuando en realidad, según cómo esté implementado isEnabled() (módulo 2), ese cambio sigue exponiendo a la mitad de los mismos usuarios a la misma latencia rota. Por qué pasa: bajar un número se siente como una acción de rollback, aunque técnicamente no apague nada para nadie que ya estuviera expuesto de forma determinista. Cómo detectarlo: si después de "revertir" sigue habiendo usuarios reales viendo la latencia rota, no se activó la red — se ajustó el dial. Cómo corregirlo: como en el ejemplo de esta lección, la red de seguridad real es el kill switch —enabled = false—, no un ajuste incremental del porcentaje.
Medir el costo del kill switch solo en la etapa donde ya estás, sin notar que es constante. Qué pasa: alguien calcula que el kill switch tarda 2 minutos en rollout 10%, y asume —sin verificarlo— que ese número va a crecer si el problema se detecta más tarde, en una etapa con más usuarios expuestos. Por qué pasa: es intuitivo pensar que "revertir algo más grande" toma más tiempo, como pasaría con stepDown. Cómo detectarlo: la pregunta correctora es "¿el costo de este mecanismo depende de cuántos usuarios están expuestos, o no?" Si la respuesta es "no depende", como pasa con un booleano, el costo es constante sin importar la etapa. Cómo corregirlo: verifica, como hizo el ejemplo de esta lección, que el mecanismo de reversión no escale con el tamaño de la exposición — esa es precisamente la propiedad que lo convierte en una red de seguridad confiable.
Tratar la existencia del kill switch como excusa para no calcular nunca el costo de un fix hacia adelante. Qué pasa: como el kill switch es tan rápido, un equipo empieza a asumir que siempre es la mejor opción, sin considerar nunca si un fix hacia adelante podría ser, en algún caso particular, igual de rápido o más apropiado. Por qué pasa: 2 minutos es un número tan bajo que compararlo contra cualquier otra cosa se siente como una pérdida de tiempo. Cómo detectarlo: si nadie en el equipo puede nombrar una situación —ni siquiera hipotética— en la que valdría la pena no usar el kill switch, probablemente no se está pensando en el costo real de cada opción, solo en el hábito. Cómo corregirlo: la lección 3 muestra un caso real, con datos, donde el costo de revertir supera al de un fix acotado — el kill switch es la opción rápida por defecto, no la opción automática sin excepciones.
Ejercicios
Ejercicio 1 — Calcula el costo en la etapa rollout 50%. Usando la misma lógica de revertLatency(), y sabiendo que minDwellHours para rollout 50% es 24 horas (tabla del proyecto del módulo 3), ¿cuánto tardaría stepDown si el guardrail se hubiera roto en esa etapa en vez de en rollout 10%? ¿Y killSwitch?
Ver solución
stepDown tardaría 24 horas —el dwellMinutesAtCurrentStage correspondiente a rollout 50%, el doble que en rollout 10%—. killSwitch seguiría tardando exactamente 2 minutos, sin cambio, porque su costo no depende de dwellMinutesAtCurrentStage en absoluto — la función ni siquiera consulta ese valor cuando mechanism === 'killSwitch'. Esta es la propiedad central de la lección: mientras más alto sube la rampa, más grande se vuelve la brecha entre las dos opciones, y más claro queda por qué la red de seguridad tiene que ser algo que no dependa de la etapa.
Ejercicio 2 — Encuentra el punto débil del argumento. Alguien del equipo objeta: "el kill switch apaga recommendations, pero no arregla la query lenta que causó la latencia rota — entonces técnicamente no 'revertimos' nada, solo escondimos el síntoma". ¿Tiene razón? ¿En qué sentido sí, y en qué sentido esa objeción se equivoca sobre lo que un rollback está diseñado para hacer?
Ver solución
Tiene razón en un sentido literal y limitado: el kill switch no toca el código de la query lenta, así que la causa raíz sigue existiendo en el sistema después de apagar la exposición. Pero la objeción se equivoca sobre el propósito del rollback: un rollback nunca prometió arreglar la causa raíz — prometió detener el daño mientras la causa raíz se investiga con calma, sin la presión de usuarios expuestos en ese mismo momento. Confundir "revertir el daño visible" con "arreglar el problema de fondo" es exactamente el error que el módulo 2 ya nombró sobre el kill switch en general, y que esta lección repite en el contexto específico de un incidente: apagar la exposición compra tiempo — no es, por sí solo, la solución completa.
Ejercicio 3 — Explica la red sin usar la palabra "rollback". En dos o tres frases, explica a alguien de otro equipo por qué Mercado necesita una forma de "achicar" la exposición de una feature que no tarde más mientras más gente ya la esté viendo. Puedes usar la analogía del trapecista.
Ver solución
Un ejemplo de respuesta: "Necesitamos una forma de apagar una feature que tarde lo mismo sin importar a cuánta gente le esté llegando en ese momento — como la red debajo de un trapecista, que atrapa la caída sin importar desde qué altura ocurrió. Si nuestra única forma de apagar algo dependiera de ir bajando poco a poco, con el mismo cuidado que usamos para subir, entonces mientras más éxito tuviera el lanzamiento —mientras más alto hubiera subido antes de romperse— más tiempo tardaríamos en protegernos de un problema ya conocido, justo cuando menos tiempo tenemos para esperar." La idea central: la red de seguridad tiene que ser rápida precisamente en el peor momento — cuando el problema ya alcanzó a más gente, no menos.
Resumen y siguiente paso
En esta lección nombraste el rollback como lo que es en el contexto de esta guía: el kill switch del módulo 2, entendido ahora como una red de seguridad — no un Ctrl+Z que rebobina el tiempo, sino un mecanismo que detiene el daño en curso, sin importar en qué etapa de la rampa se rompió el guardrail. Con revertLatency() mediste el contraste real: 2 minutos con el kill switch contra 12 horas si el único mecanismo disponible fuera retroceder la rampa un escalón a la vez, con la misma cautela usada para subirla.
Antes de avanzar deberías poder: explicar por qué el costo del kill switch no depende de la etapa del rollout; distinguir "apagar la exposición" de "arreglar la causa raíz", como dos cosas distintas que el rollback no promete confundir; y calcular, para cualquier etapa de la rampa, cuánto tardaría cada mecanismo de reversión.
Ya tienes la mitad de la información que hace falta para decidir entre revertir y arreglar hacia adelante: el costo de revertir. La lección 3 construye la otra mitad —el costo de un fix hacia adelante— y las junta en rollbackDecision(), el modelo que toma la decisión completa sobre el caso real de recommendations.
Recursos
- LaunchDarkly, "What Is a Kill Switch in Software Development?" — launchdarkly.com/blog/what-is-a-kill-switch-software-development. El mismo artículo del módulo 2, ahora en el contexto de un incidente real: describe el kill switch explícitamente como el mecanismo de reversión más rápido disponible cuando algo sale mal en producción. En inglés.
- Charity Majors, "Deploys Are the WRONG Way to Change User Experience" — honeycomb.io/blog/deploys-wrong-way-change-user-experience. El argumento central de por qué un flag revierte una experiencia de usuario en minutos, mientras que revertir a nivel de despliegue de código puede tardar mucho más — la base de la comparación que hizo esta lección. En inglés.
- Google SRE Workbook, Capítulo 16, "Canarying Releases" — sre.google/workbook/canarying-releases. La misma referencia del proyecto del módulo 3: el
dwellMinutesAtCurrentStageque esta lección reutiliza como el costo destepDownviene directamente del protocolo de avance cauteloso que este capítulo describe. En inglés.