Módulo 1: From Experiment To Launch
El radio de impacto: cuánta gente real toca un error conocido
Descripción
La lección 3 dejó el marco en palabras: qué tan grave si sale mal, qué tan fácil volver atrás. Esta lección convierte la primera coordenada —"qué tan grave"— en un número exacto. El concepto se llama blast radius, radio de impacto: cuántos usuarios reales quedan expuestos a un problema conocido, según qué fracción de la base recibe el cambio primero. No es una métrica abstracta — la vas a calcular, hoy, sobre el guardrail de latencia roto de recommendations, comparando tres formas distintas de lanzar el mismo cambio.
Conexión con el módulo. Esta lección ejecuta el modelo central de todo el módulo 1: blastRadius(), la pieza de aritmética que las lecciones 2 y 3 prepararon en prosa y que la lección 7 va a usar para cerrar el argumento del módulo. No enseña cómo se construye técnicamente un lanzamiento gradual —eso es el módulo 3—; enseña por qué la fracción de usuarios expuestos es, por sí sola, la palanca más poderosa que tienes para contener un daño ya conocido.
Una analogía: la explosión y el radio que alcanza
Cuando un ingeniero de demoliciones planea derribar un edificio, no calcula solo si la explosión va a funcionar — calcula, con precisión, hasta dónde llega la onda expansiva: qué tan lejos del punto de detonación hay riesgo real para las estructuras vecinas, los vehículos, la gente. Ese cálculo —el "radio de impacto" literal, de donde toma el nombre el concepto de esta lección— es la diferencia entre una demolición controlada y un desastre: la explosión en sí puede ser idéntica, pero el radio que se decide exponer a ella (evacuando una manzana, o diez) cambia por completo cuánta gente puede salir lastimada.
Un lanzamiento de software tiene el mismo cálculo, con una ventaja enorme sobre la demolición física: el radio de impacto es una elección, no una propiedad fija del cambio. El ingeniero de demoliciones no puede hacer que la onda expansiva llegue más lejos o más cerca sin cambiar la cantidad de explosivo. Tú sí puedes decidir, con total libertad, si recommendations la ve el 100% de Mercado o el 1% — la regresión de latencia es la misma en cualquier caso, pero cuánta gente la sufre depende enteramente de esa decisión.
Ejemplo trabajado: blastRadius() sobre el lanzamiento de recommendations
El guardrail de latencia de Mercado ya está roto: p95 pasó de 650ms a 910ms, por encima del techo de 800ms, dentro del propio experimento. Vamos a modelar cuánta gente sufre esa regresión, según qué fracción de la base de 250,000 compradores recibe el cambio:
// blastRadius: cuantos usuarios reales quedan expuestos a una regresion conocida,
// segun que fraccion de la base recibe el lanzamiento primero.
// Caso pedagogico: recommendations en Mercado. El A/B gano en conversion (+18.75%,
// p=0.0114) pero rompio el guardrail de latencia (p95 650ms -> 910ms, techo 800ms).
// Esa regresion ya es un HECHO conocido antes de lanzar a produccion completa --
// la pregunta no es "existe el riesgo", es "a cuanta gente se lo expones primero".
function blastRadius({ totalUsers, rolloutPercent, regressionRate }) {
const exposedUsers = Math.round(totalUsers * rolloutPercent);
const affectedUsers = Math.round(exposedUsers * regressionRate);
return { rolloutPercent, exposedUsers, affectedUsers };
}
const totalUsers = 250000; // base de compradores alcanzable por recommendations (misma cifra que product-metrics)
const regressionRate = 0.05; // fraccion de usuarios expuestos que sufre la regresion de latencia conocida (rompe el guardrail de 800ms)
const stages = [
{ label: 'ship a 100% de golpe', rolloutPercent: 1.0 },
{ label: 'rollout a 10%', rolloutPercent: 0.10 },
{ label: 'canary a 1%', rolloutPercent: 0.01 },
];
console.log('=== blastRadius: recommendations de Mercado (regressionRate=5%) ===\n');
const results = stages.map((s) => ({ ...s, ...blastRadius({ totalUsers, rolloutPercent: s.rolloutPercent, regressionRate }) }));
results.forEach((r) => {
console.log(r.label.padEnd(22) + 'exposedUsers=' + r.exposedUsers.toLocaleString('en-US').padStart(7) +
' affectedUsers=' + r.affectedUsers.toLocaleString('en-US').padStart(6));
});
const worst = results[0].affectedUsers;
const best = results[2].affectedUsers;
console.log('\nEl canary (1%) contiene el dano a ' + Math.round((best / worst) * 10000) / 100 + '% de lo que hubiera afectado el ship a 100% de golpe.');
console.log('En numeros: ' + worst.toLocaleString('en-US') + ' usuarios afectados (100% de golpe) vs ' + best.toLocaleString('en-US') + ' usuarios afectados (canary 1%) -- una diferencia de ' + (worst - best).toLocaleString('en-US') + ' personas.');
Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:
=== blastRadius: recommendations de Mercado (regressionRate=5%) ===
ship a 100% de golpe exposedUsers=250,000 affectedUsers=12,500
rollout a 10% exposedUsers= 25,000 affectedUsers= 1,250
canary a 1% exposedUsers= 2,500 affectedUsers= 125
El canary (1%) contiene el dano a 1% de lo que hubiera afectado el ship a 100% de golpe.
En numeros: 12,500 usuarios afectados (100% de golpe) vs 125 usuarios afectados (canary 1%) -- una diferencia de 12,375 personas.
⚠️ Los números (
250,000usuarios,5%de tasa de regresión) son un caso pedagógico para razonar sobre el radio de impacto; en un lanzamiento real,regressionRatesaldría de datos observados del propio experimento o de un canary previo, no de una estimación a priori.
Fíjate en la forma de la tabla: el regressionRate —la probabilidad de que un usuario expuesto sufra la regresión— es el mismo 5% en las tres filas. Nada sobre la gravedad del bug cambió entre una fila y otra. Lo único que cambió es rolloutPercent, y eso solo bastó para mover affectedUsers de 125 a 12,500 — una diferencia de 100 veces. Ese es el punto completo de esta lección: el radio de impacto no es una propiedad del error en sí, es una propiedad de cuánta gente decides exponer a él antes de saber si está contenido.
Por qué el radio de impacto es la palanca más poderosa que tienes
Nota algo importante sobre el modelo: blastRadius() no arregla el bug. La latencia sigue rota en el 5% de los casos, sin importar cuál fila mires. Lo que el modelo muestra es que arreglar el bug y contener su radio de impacto son dos acciones distintas, y no necesitas esperar a la primera para empezar la segunda. Un equipo que insiste en "arreglemos la latencia antes de lanzar nada" retrasa por completo el valor de recommendations (el +18.75% en conversión que sí es real). Un equipo que entiende el radio de impacto puede lanzar ahora, empezando en el 1%, mientras el equipo de latencia trabaja en el fix en paralelo — con solo 125 personas, en vez de 12,500, pagando el costo mientras tanto.
Esta es la razón por la que el radio de impacto se vuelve el concepto que sostiene el resto de la guía: el módulo 3 (rollout gradual) es, en esencia, una rampa diseñada explícitamente para mantener el radio de impacto chico el mayor tiempo posible; el módulo 4 (monitoreo) existe para detectar, en cada etapa de esa rampa, si el radio de impacto está creciendo hacia un problema; y el módulo 5 (rollback) es lo que se activa cuando decides que ni siquiera el radio actual es aceptable.
Errores comunes
Pensar que un regressionRate bajo (5%) hace que el problema no importe. Qué pasa: alguien ve regressionRate: 0.05 y concluye que, como "solo" el 5% se ve afectado, no vale la pena preocuparse por el porcentaje de rollout. Por qué pasa: 5% suena a un número chico en abstracto, y es fácil olvidar que ese porcentaje se aplica sobre una base absoluta enorme. Cómo detectarlo: la conversación se queda en el porcentaje (5%) y nunca llega al número absoluto de personas (12,500 en el peor caso). Cómo corregirlo: siempre convierte el porcentaje a personas reales, como hace blastRadius() — 5% de 250,000 es 12,500 personas con una experiencia de checkout degradada, un número que ningún equipo de producto trataría como "no importa" si lo viera escrito así.
Confundir "arreglar el bug" con "reducir el radio de impacto" — y pensar que hace falta lo primero antes de empezar lo segundo. Qué pasa: el lanzamiento se congela por completo hasta que el equipo de ingeniería resuelve la regresión de latencia, perdiendo semanas de la mejora real en conversión mientras tanto. Por qué pasa: "hay un bug conocido" se siente como razón suficiente para no tocar nada, sin distinguir entre exponer a 12,500 personas y exponer a 125. Cómo detectarlo: la propuesta sobre la mesa es "esperemos al fix" sin ninguna propuesta alternativa de "lancemos con radio de impacto controlado mientras tanto". Cómo corregirlo: como en el ejemplo de hoy, recuerda que son dos acciones independientes — contener el radio de impacto (con qué fracción expones) no depende de haber arreglado el bug primero, y te permite capturar valor real mientras el arreglo avanza en paralelo.
Tratar el 100 vs 1 de la comparación como si fuera solo un ejercicio matemático, sin conectar el número con personas reales afectadas. Qué pasa: el equipo mira la tabla de blastRadius(), dice "interesante" y sigue de largo, sin que el número 12,375 (la diferencia entre las dos estrategias) cambie ninguna decisión concreta. Por qué pasa: números en una tabla de consola se sienten abstractos hasta que alguien los traduce en la pregunta correcta: "¿estamos dispuestos a que 12,375 personas más sufran esta regresión, solo para ahorrarnos el trabajo de un rollout gradual?" Cómo detectarlo: después de ver la tabla, nadie propone explícitamente un porcentaje de arranque distinto de 100%. Cómo corregirlo: usa el resultado de blastRadius() como insumo directo de una decisión — no como una curiosidad — exactamente como hace el mini-proyecto de esta guía en la lección 8.
Ejercicios
Ejercicio 1 — Calcula un cuarto escenario. Usa blastRadius() mentalmente (o a mano) para calcular exposedUsers y affectedUsers de un rollout al 50%, con los mismos totalUsers: 250000 y regressionRate: 0.05 del ejemplo. ¿Dónde cae este resultado, comparado con las tres filas de la tabla original?
Ver solución
exposedUsers = round(250000 * 0.5) = 125,000. affectedUsers = round(125000 * 0.05) = 6,250. Cae exactamente a mitad de camino entre el 10% (1,250 afectados) y el 100% (12,500 afectados) — de hecho, es justo la mitad del peor caso, como corresponde a estar en el 50% de rollout. Este es el punto donde, en un rollout gradual real (módulo 3), el radio de impacto empieza a acercarse al peor caso — razón de más para haber vigilado el guardrail de cerca (módulo 4) mucho antes de llegar aquí.
Ejercicio 2 — Cambia la variable que de verdad importa. Supón que, gracias a un fix parcial del equipo de ingeniería, regressionRate baja de 0.05 a 0.01 (1%), pero el equipo todavía decide lanzar al 100% de golpe. Calcula affectedUsers en este nuevo escenario. ¿Sigue siendo mejor idea que un canary al 1% con el regressionRate original de 0.05?
Ver solución
affectedUsers = round(250000 * 1.0 * 0.01) = 2,500. Comparado con el canary original (125 afectados, con regressionRate: 0.05 y rolloutPercent: 0.01), 2,500 sigue siendo veinte veces peor, a pesar de que el bug es cinco veces menos frecuente. La lección aquí es que mejorar el bug (bajar regressionRate) y controlar el radio de impacto (bajar rolloutPercent) son dos palancas independientes, y ninguna sustituye completamente a la otra — la combinación más segura sigue siendo bajar las dos: arreglar lo que se pueda del bug, y lanzar empezando chico.
Ejercicio 3 — Diseña tu propio caso. Piensa en una regresión conocida de tu propio trabajo (real o hipotética) — puede ser una latencia más alta, un error de UI, un cálculo incorrecto en un caso raro. Estima un totalUsers y un regressionRate razonables, y calcula (a mano o corriendo el código) el affectedUsers comparando 100% contra un canary del 1%. ¿El resultado te sorprende?
Ver solución
No hay una respuesta única —depende de tu caso—, pero el patrón se repite siempre: la razón entre affectedUsers al 100% y al 1% es, matemáticamente, siempre 100 (porque blastRadius() escala de forma lineal con rolloutPercent, y el regressionRate se cancela en la razón). Lo que cambia caso a caso es el número absoluto de personas detrás de ese 100x — y ese número absoluto es exactamente lo que vuelve concreta una decisión que, en abstracto ("5% de regresión"), suena manejable.
Resumen y siguiente paso
En esta lección ejecutaste blastRadius(), el modelo central del módulo, sobre el lanzamiento real de recommendations: con el mismo regressionRate del 5%, lanzar al 100% de golpe expone a 12,500 personas a la regresión de latencia conocida; un canary al 1% expone a solo 125 — cien veces menos—. Viste que el radio de impacto no es una propiedad fija del bug, sino una decisión completamente tuya sobre cuánta gente expones primero, y que contener el radio de impacto no depende de haber arreglado el bug de antemano.
Antes de avanzar deberías poder: explicar con tus propias palabras qué es el radio de impacto y por qué escala con el porcentaje de rollout; ejecutar blastRadius() a mano para un porcentaje nuevo; y argumentar por qué "arreglar el bug" y "reducir el radio de impacto" son dos acciones independientes que se pueden hacer en paralelo.
La lección 5 toma un paso atrás y nombra una distinción que hace posible controlar el radio de impacto en primer lugar: la diferencia entre que el código esté en producción y que los usuarios lo vean. Sin esa separación, no hay forma de exponer solo al 1% — el código, sencillamente, está encendido o apagado para todos a la vez.
Recursos
- Google SRE Workbook, Capítulo 16, "Canarying Releases" — sre.google/workbook/canarying-releases. El capítulo de referencia que define el canary como "un despliegue parcial y limitado en el tiempo, evaluado antes del despliegue completo" — la base formal del modelo
blastRadius()de esta lección. En inglés. - AWS Well-Architected Framework, Pilar de Confiabilidad, "Implement Change" — docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/implement-change.html. Documentación oficial de AWS que usa explícitamente el término "blast radius" y recomienda feature flags, despliegues canary y aislamiento por zona como formas de reducirlo. En inglés.