wandres.dev
EL CASO DE NEGOCIO · Convertir milisegundos en dinero

El experimento propio, hecho de forma honesta

Los cinco diseños ordenados por rigor, el cálculo de tamaño de muestra que dice si puedes permitirte el experimento, las cuatro comprobaciones de validez, y qué hacer cuando no tienes tráfico suficiente.

⏱ 21 min

Medirlo tú es la única forma de saberlo, y es más fácil de lo que parece siempre que se hagan las cuentas antes. La cuenta que hay que hacer primero no es la del efecto esperado sino la del tamaño de muestra, porque determina si el experimento es posible con tu tráfico o si vas a pasar tres semanas produciendo un resultado que no distingue nada de nada. Ese cálculo cabe en cinco líneas y descarta la mitad de los experimentos que se proponen.

🎯 Al terminar esta lección sabrás
  • Elegir entre los cinco diseños según el rigor que permita tu situación.
  • Calcular el tamaño de muestra necesario y decidir si el experimento es viable.
  • Aplicar las cuatro comprobaciones de validez, empezando por la del reparto.
  • Sustituir la métrica final por una intermedia cuando falta potencia estadística.

Los cinco diseños

Ordenados de más a menos rigor causal.

Uno: retardo aleatorizado. Inyectas un retardo artificial a una fracción aleatoria de usuarios y mides. Es el único diseño que aísla la latencia perfectamente, porque lo único que cambia entre los grupos es el tiempo. Su pega es evidente y hay que tratarla de frente: estás empeorando el servicio a propósito para una parte de tus usuarios. Se hace de forma responsable con retardos pequeños, durante poco tiempo, excluyendo los pasos críticos como el pago, y con aprobación explícita de quien corresponda. A cambio, es el diseño que produce un número en el que se puede confiar.

// En el servidor. Retardo aleatorizado por usuario, no por peticion.
import { createHash } from 'node:crypto';

const RETARDO_MS = 300;
const RUTAS_EXCLUIDAS = ['/pago', '/carrito', '/cuenta'];

function grupo(idUsuario) {
  const h = createHash('sha256').update(`exp-latencia:${idUsuario}`).digest();
  return h[0] % 2 === 0 ? 'control' : 'retardado';
}

export async function middleware(peticion, siguiente) {
  const id = peticion.cookies.get('uid')?.value;
  const ruta = new URL(peticion.url).pathname;

  if (!id || RUTAS_EXCLUIDAS.some((r) => ruta.startsWith(r))) {
    return siguiente();
  }

  const g = grupo(id);
  // La marca viaja con cada evento de analitica.
  peticion.headers.set('x-exp-latencia', g);

  if (g === 'retardado') {
    await new Promise((r) => setTimeout(r, RETARDO_MS));
  }
  return siguiente();
}

El uso de un hash del identificador en lugar de un número aleatorio es deliberado: el grupo queda determinado por el usuario y es estable entre peticiones y entre servidores, sin necesidad de guardar nada. Con Math.random() en cada petición, un mismo usuario alternaría de grupo y el experimento no mediría nada.

Dos: mejora aleatorizada. Construyes la versión optimizada y la sirves a una mitad. No perjudica a nadie, y a cambio exige mantener las dos versiones y aceptar que estás manipulando más de una variable si la optimización cambió también el código.

Tres: despliegue por fases con grupo retenido. Despliegas la mejora al noventa por ciento y dejas un diez por ciento con la versión anterior durante unas semanas. Es una variante muy práctica de la anterior, porque encaja con un proceso de despliegue que ya existe, y suele ser la más fácil de conseguir políticamente: nadie se opone a un despliegue progresivo.

Cuatro: diferencias en diferencias. Sin aleatorizar. Comparas la evolución de la sección mejorada con la de una sección comparable no tocada. Requiere el supuesto de tendencias paralelas y es comprobable mirando los meses anteriores.

Cinco: experimento natural. Aprovechas algo que ocurrió por su cuenta: una caída de la red de distribución que afectó a una región, una migración que cambió la latencia de un país. Barato y oportunista; la asignación no es aleatoria y hay que argumentar por qué se parece a serlo.

El cálculo que decide si puedes

Antes de nada, el tamaño de muestra. Para comparar dos proporciones con una potencia del ochenta por ciento y un nivel de significación del cinco por ciento, la regla práctica es:

n por grupo = 16 x p x (1 - p) / delta^2

  p     = tasa base de la metrica
  delta = diferencia ABSOLUTA que quieres poder detectar

Los números que salen son la parte incómoda:

function tamanoDeMuestra(tasaBase, mejoraRelativa) {
  const delta = tasaBase * mejoraRelativa;
  const n = (16 * tasaBase * (1 - tasaBase)) / (delta * delta);
  return Math.ceil(n);
}

// Conversion del 2 %, quiero detectar una mejora relativa del 2 %.
tamanoDeMuestra(0.02, 0.02);   // 1.960.000 por grupo

// La misma, pero detectando un 10 % relativo.
tamanoDeMuestra(0.02, 0.10);   // 78.400 por grupo

// Una metrica con base alta: anadir al carrito, 12 %.
tamanoDeMuestra(0.12, 0.10);   // 9.778 por grupo

// Tasa de rebote del 45 %, mejora relativa del 5 %.
tamanoDeMuestra(0.45, 0.05);   // 3.912 por grupo

Lee esa tabla despacio porque contiene la decisión entera. Detectar una mejora del dos por ciento sobre una conversión del dos por ciento exige casi dos millones de usuarios por grupo. Si tu sitio recibe cien mil visitantes al mes, ese experimento tardaría más de tres años y no lo vas a hacer. Y la aritmética no negocia: el tamaño crece con el cuadrado del inverso del efecto, así que detectar la mitad de efecto cuesta cuatro veces más.

De ahí salen las tres salidas cuando no llegas, en orden de preferencia:

Sube el tamaño del efecto que buscas. No midas un retardo de cien milisegundos: mide uno de mil. El efecto será mucho mayor y detectable, y de la relación entre los dos puntos puedes razonar hacia abajo con una hipótesis explícita. Es la salida más limpia y la que más se descarta por prudencia mal entendida.

Cambia a una métrica de base más alta. Las últimas dos filas del ejemplo lo dicen todo: pasar de la conversión final a añadir al carrito baja el requisito de dos millones a diez mil. La métrica intermedia tiene además una ventaja causal, y es que está más cerca del mecanismo: si la velocidad afecta a la conversión, tiene que afectar antes a algo intermedio.

Acepta que no puedes medirlo y dilo. Es una conclusión legítima y a menudo la correcta. Un sitio pequeño no puede medir efectos pequeños, y presentar como resultado algo que tu diseño no puede detectar es peor que no medir. Lo que sí puedes medir con poco tráfico son cosas grandes: el abandono de carga, los errores, los tiempos absolutos.

Las cuatro comprobaciones de validez

Uno: el reparto de la muestra. La comprobación más importante y la que menos se hace. Si repartes al cincuenta por ciento, los dos grupos deben tener tamaños casi iguales; si no los tienen, hay un fallo en la asignación o en la recogida y el resultado no vale. Una desviación mayor de lo que el azar explica suele indicar que uno de los grupos pierde eventos, cosa habitual cuando la variante más lenta hace que más usuarios se marchen antes de que se envíe la telemetría, que es exactamente el sesgo que arruinaría el experimento.

// Chi cuadrado con un grado de libertad. Por encima de 10,83
// la probabilidad de que sea azar es menor que 1 entre 1000.
function repartoCorrecto(nA, nB, proporcionEsperadaA = 0.5) {
  const total = nA + nB;
  const espA = total * proporcionEsperadaA;
  const espB = total * (1 - proporcionEsperadaA);
  const chi = (nA - espA) ** 2 / espA + (nB - espB) ** 2 / espB;
  return { chi: Number(chi.toFixed(2)), sospechoso: chi > 10.83 };
}

repartoCorrecto(48120, 51880);   // { chi: 53.79, sospechoso: true }

Dos: una prueba A/A antes. Ejecuta el experimento con las dos ramas idénticas durante unos días. Si sale una diferencia significativa, tu tubería de datos tiene un problema y lo has descubierto antes de sacar conclusiones falsas de un experimento real. Cuesta unos días y evita el error más caro de todos.

Tres: no mirar antes de tiempo. Comprobar el resultado cada día y parar cuando salga significativo multiplica la tasa de falsos positivos, por la misma aritmética de comparaciones múltiples de las comprobaciones automáticas. Fija la duración de antemano y respétala. Si necesitas mirar por el camino, existen métodos secuenciales diseñados para eso; lo que no vale es mirar con un método pensado para no mirar.

Cuatro: al menos dos semanas completas. Cubre los dos ciclos semanales y deja pasar los efectos de novedad. Un experimento de tres días mide el martes.

Registrar antes de empezar

La práctica que separa un experimento honesto de un ejercicio de confirmación es escribir el plan antes de ver ningún dato. Cabe en un documento corto y hay que fecharlo:

Hipotesis        Reducir el LCP p75 movil de 4,1 s a 2,4 s aumenta la
                 tasa de anadir al carrito en movil.
Diseno           Despliegue por fases con retencion del 20 % durante 21 dias.
Unidad           Usuario, identificado por cookie de primera parte.
Metrica primaria Tasa de sesiones con al menos un anadir al carrito, en movil.
Base actual      11,8 %
Efecto minimo    +8 % relativo (a 12,74 %)
Muestra          15.300 sesiones por grupo. Con 2.900/dia llegamos en 11 dias.
Duracion         21 dias completos. No se mira antes del dia 21.
Secundarias      Rebote, paginas por sesion, conversion final (sin potencia).
Guardarrailes    Errores de JS, tasa de reembolsos, tiempo de respuesta del origen.
Validez          A/A previo de 5 dias. Chi cuadrado del reparto cada dia.
Decision         Si el intervalo de la diferencia excluye el cero y es positivo,
                 se despliega al 100 % y se invierte en la siguiente ruta.
                 Si incluye el cero, se para el programa y se documenta.

La última línea es la que hace que esto sea un experimento y no una justificación. Comprometerse por escrito con qué se hace si sale que no, antes de saberlo, es lo que evita la reinterpretación creativa de un resultado nulo. Y también es lo que hace que el siguiente experimento te lo aprueben sin discusión.

Un resultado nulo es un resultado, y sabérselo aceptar es lo que te compra permiso para el siguiente experimento

Vas a encontrarte, con más frecuencia de la que la literatura pública sugiere, con experimentos que no detectan nada. El intervalo de confianza contiene el cero, la diferencia es de dos décimas en una u otra dirección, y el resultado no autoriza a afirmar nada. Ese momento es el que define qué clase de ingeniero eres delante de tu organización, y hay dos caminos. El primero es el que toma casi todo el mundo: buscar el segmento donde sí sale, probar con otra métrica, alargar el experimento unos días más a ver si cruza. Todo eso tiene nombre en estadística, se llama dragar los datos, y produce un número que se puede presentar y que es falso. El problema no es solo ético: es que ese número no va a replicarse, la mejora prometida no se va a materializar en el trimestre siguiente, y la próxima vez que pidas presupuesto para rendimiento alguien se acordará. Has cambiado credibilidad futura por una victoria presente, y en una organización la credibilidad es la moneda con la que se compran los proyectos difíciles. El segundo camino es informar del resultado nulo tal cual, y viene con tres recompensas que no son obvias. La primera: acabas de acotar el efecto por arriba, que es información real y útil. “Si hay efecto, es menor del cuatro por ciento” te dice cuánto tiene sentido invertir aquí, y eso es exactamente lo que un buen gestor necesita para decidir. La segunda: has demostrado que tu tubería produce resultados que no siempre te convienen, y eso hace que el siguiente resultado positivo se crea sin discusión. Un equipo que solo publica resultados favorables no es creíble y todo el mundo lo sabe. La tercera, la más práctica: un resultado nulo suele significar que el cuello de botella está en otro sitio, y esa es una pista valiosísima que te ahorra el trimestre que ibas a gastar optimizando lo que no importaba. Piensa además en la asimetría de lo que hay en juego. Un resultado positivo mal obtenido te da un proyecto de tres meses que probablemente no va a demostrar nada al final. Un resultado nulo bien obtenido te da una reputación de persona que mide de verdad, y con eso se aprueban los proyectos siguientes casi sin justificación. En cualquier organización que dure, la honestidad metodológica no es un lujo moral: es la estrategia con mejor rendimiento a dos años.

⚔️ Diseña y ejecuta uno
  1. Calcula el tamaño de muestra para tu métrica de conversión y para una métrica intermedia. Decide cuál es viable.
  2. Escribe el registro previo completo, con la línea de qué se hace si sale nulo, y fírmalo con fecha.
  3. Ejecuta una prueba A/A de cinco días y comprueba que no detecta nada.
  4. Implementa la asignación estable por hash del identificador y verifica el reparto con el chi cuadrado cada día.
  5. Ejecuta el experimento sin mirar hasta la fecha comprometida, e informa del resultado sea el que sea.