Módulo 5: Thresholds — pasa/falla y SLOs
5. SLO/SLA: elegir el umbral con criterio
Descripción
Todo el mecanismo de los módulos anteriores es preciso: mides el p95 con rigor, lo comparas con un umbral, sale un veredicto, el veredicto se vuelve un código de salida que gatea el deploy. Pero hay un número en el centro de toda esa maquinaria que no hemos justificado: el 200 de p(95) < 200. ¿Por qué 200 y no 150, o 500, o 1000? Esta lección responde esa pregunta, y la respuesta es incómoda para un ingeniero: el valor del umbral no es una decisión técnica, es una decisión de negocio y de usuario. Un gate perfecto con un umbral arbitrario no protege nada —o rechaza builds sanos, o deja pasar apps lentas—. Vas a aprender el vocabulario que la industria usa para elegir estos números con criterio —SLI, SLO, SLA y el error budget—, de dónde sale un umbral que sí significa algo, y por qué un umbral demasiado holgado vuelve el gate inútil mientras uno demasiado estricto lo vuelve inestable. Y lo verás ejecutado de la forma más contundente posible: la misma carga, con el mismo p95 medido, pasando contra un umbral y fallando contra otro —prueba viva de que el threshold es una elección, no un dato que la naturaleza entrega—.
Conexión con el módulo: las lecciones 2–4 te dieron la maquinaria del threshold (la regla, el veredicto, el exit code) tratando el valor del umbral como un dato de entrada. Esta lección llena ese hueco: cómo se elige ese valor. Es la bisagra entre lo técnico y lo humano del módulo. Lo que sigue (lección 6) muestra que este mismo gate es hermano de los coverage gates; la 7 pone umbrales distintos a partes distintas del sistema —lo cual solo tiene sentido si sabes elegir cada uno—. Aquí aprendes a poner el número.
El límite de velocidad no lo pone el coche
¿Por qué el límite en una autopista es 120 km/h y no 90, o 160? No lo decidió el ingeniero que diseñó el coche —el motor da para 200—. Lo decidió alguien mirando otra cosa: cuánto tarda un coche en frenar, qué tan grave es un choque a cada velocidad, cuánta gente muere de más por cada 10 km/h extra. El número sale del daño aceptable para las personas, no de la capacidad de la máquina. Un límite de 300 km/h sería inútil (nunca se rompería, no protege a nadie); uno de 40 sería absurdo (todo el mundo lo violaría, y frenaría la economía sin ganar seguridad proporcional). El buen límite vive en el punto donde el costo para el usuario empieza a ser inaceptable.
Un umbral de rendimiento es idéntico. El 200 de p(95) < 200 no sale de lo que tu servidor puede hacer, sino de lo que tu usuario tolera antes de que la experiencia se degrade. La investigación de usabilidad tiene puntos de referencia: alrededor de 100 ms una interacción se siente instantánea; hasta ~1 segundo el usuario mantiene el hilo de lo que hacía; pasado eso, empieza a perder la atención y a frustrarse. Para una cotización que el usuario espera en pantalla, un p95 de 200 ms significa "19 de cada 20 usuarios sienten la app ágil". Ese es el razonamiento detrás del número: el límite lo pone el daño al usuario, no el motor.
El vocabulario: SLI, SLO, SLA
La disciplina que formaliza esto es la ingeniería de confiabilidad de sitios (SRE, por Google), y tiene tres términos que conviene no confundir, porque cada uno vive en una capa distinta:
- SLI — Service Level Indicator (indicador). Qué mides. Es la métrica cruda: "el p95 de la latencia de
POST /quote", "el porcentaje de peticiones con status < 400". Un SLI es un hecho medible. Los módulos 3 y 4 fueron enteros sobre producir SLIs. - SLO — Service Level Objective (objetivo). Qué te propones cumplir. Es el SLI más un umbral y un objetivo: "el p95 de
/quoteestará por debajo de 200 ms el 99% del tiempo". El SLO es la meta interna que el equipo se compromete a mantener. El threshold de tu gate es un SLO hecho ejecutable. - SLA — Service Level Agreement (acuerdo). Qué le prometes a un cliente por contrato, con consecuencias. Es un SLO escrito en un contrato comercial, con penalizaciones si se incumple: "si la disponibilidad baja del 99.9% mensual, te devolvemos el 10%". El SLA suele ser más laxo que el SLO interno, a propósito: el equipo se pone una meta más estricta (SLO) para tener margen antes de romper la promesa contractual (SLA).
La cadena es: mides un SLI, te comprometes con un SLO (el SLI + umbral), y quizás le prometes a un cliente un SLA (un SLO contractual). Tu threshold —p(95) < 200— es la forma ejecutable de un SLO. Cuando el gate pasa, estás cumpliendo tu objetivo de servicio; cuando falla, lo estás incumpliendo. Por eso elegir el umbral es elegir tu SLO, y elegir tu SLO es un acto de negocio: define qué le prometes, implícita o explícitamente, a tus usuarios.
El error budget: por qué el umbral no es "siempre"
Fíjate en un detalle del SLO de arriba: "el p95 estará bajo 200 ms el 99% del tiempo". No dice "siempre". Ese reconocimiento de que la perfección no es la meta se formaliza en el error budget (presupuesto de error): si tu objetivo es cumplir el 99% del tiempo, tienes un 1% de presupuesto para incumplir sin romper la promesa. Ese 1% no es un fracaso a evitar a toda costa: es un recurso que puedes gastar —en desplegar rápido, en experimentar, en asumir riesgos—. Un equipo que nunca gasta su error budget probablemente puso un SLO demasiado laxo y está siendo excesivamente conservador; uno que lo agota todo el tiempo tiene un problema de confiabilidad real.
Para un gate de rendimiento, el error budget tiene una consecuencia práctica: no vuelvas el umbral tan estricto que gaste el presupuesto en ruido. Si tu p95 real ronda los 190 ms con variación natural, un umbral de p(95) < 200 va a fallar de vez en cuando por pura suerte del muestreo —un gate inestable (flaky), que reprueba builds sanos y enseña al equipo a ignorar el rojo—. El error budget te recuerda que el umbral debe dejar margen para la variación normal: se pone donde separa "esto es una regresión real" de "esto es ruido", no pegado al valor típico.
La prueba viva: el mismo p95, dos veredictos
Aquí está la demostración que fija la idea entera. Vamos a medir /quote_cpu bajo la misma carga pesada (2000 peticiones, 120 concurrentes) dos veces, cambiando solo el umbral. El p95 medido será casi el mismo en ambas (la carga es la misma); lo único que cambia es la regla contra la que lo comparamos. Primero, un umbral estricto de 200 ms:
Qué esperar — con un p95 de ~243 ms, el umbral de 200 ms se rompe: FALLA, exit code 1:
$ python3.14 threshold_gate.py http://127.0.0.1:PORT /quote_cpu 2000 120 200
# /quote_cpu | 2000 peticiones, concurrencia 120
THRESHOLD MEDIDO RESULTADO
----------------------------------------------------------------------
http_req_duration: p(95) < 200ms p(95) = 242.86ms FAIL
http_req_failed: rate < 1.00% rate = 0.00% PASS
checks: rate > 99.00% rate = 100.00% PASS
----------------------------------------------------------------------
GATE: FAIL (exit code 1)
Ahora la misma carga, el mismo endpoint, un p95 prácticamente idéntico —pero con un umbral holgado de 500 ms:
Qué esperar — el p95 (~243 ms) ahora está por debajo de 500 ms: PASA, exit code 0. Nada cambió en la app; cambió la regla:
$ python3.14 threshold_gate.py http://127.0.0.1:PORT /quote_cpu 2000 120 500
# /quote_cpu | 2000 peticiones, concurrencia 120
THRESHOLD MEDIDO RESULTADO
----------------------------------------------------------------------
http_req_duration: p(95) < 500ms p(95) = 243.43ms PASS
http_req_failed: rate < 1.00% rate = 0.00% PASS
checks: rate > 99.00% rate = 100.00% PASS
----------------------------------------------------------------------
GATE: PASS (exit code 0)
Léelo despacio, porque es todo el argumento de la lección en dos corridas. La app se comportó igual las dos veces (p95 de 242.86 y 243.43 ms —la misma latencia, con el ruido normal del muestreo). El veredicto pasó de FAIL a PASS. Lo único que decidió el resultado fue el número del umbral, que elegimos nosotros. Esto demuestra, de forma imposible de discutir, que el umbral no es un dato que la medición entrega: es una decisión que tú tomas antes de medir, y que determina qué cuenta como "suficientemente bueno". La medición es objetiva (243 ms es 243 ms); la aprobación es una elección (¿243 ms es aceptable? depende de tu SLO).
De ahí la responsabilidad: si eliges 500 ms porque "así siempre pasa", tu gate no protege nada —dejarías pasar una app que hace esperar un cuarto de segundo a 1 de cada 20 usuarios—. Si eliges 200 ms porque tu usuario necesita agilidad, el gate atrapa esa degradación. El mismo mecanismo, con dos umbrales, es o un guardián o un teatro. La diferencia es enteramente el criterio con que pusiste el número.
Cómo elegir el número, en la práctica
Entonces, ¿de dónde sacas el umbral concreto para tu API? Un procedimiento sensato:
- Parte del usuario y del negocio. ¿Qué es esta operación para quien la usa? Una interacción síncrona (el usuario espera mirando la pantalla) pide un p95 bajo (cientos de ms); un trabajo en segundo plano (un reporte que se genera y se envía por correo) tolera segundos. Los puntos de referencia de usabilidad (100 ms = instantáneo, 1 s = mantiene la atención) son tu ancla.
- Mira tu línea base. Corre la prueba sin umbral y observa el p95 típico bajo carga realista. El umbral debe estar por encima de esa línea base sana con margen para la variación (para no ser flaky), pero por debajo del punto donde el usuario empezaría a sufrir (para que signifique algo).
- Elige el percentil según a quién proteges.
p(95)protege a 19 de cada 20;p(99)también a la cola extrema. Operaciones críticas (pagos, login) suelen gatear el p99; el resto, el p95. - Deja error budget. No pegues el umbral al valor típico. Ponlo donde separa regresión de ruido.
- Sé más estricto en el SLO interno que en el SLA. Si le prometes 500 ms a un cliente por contrato, gatea tu CI en 400: así te enteras antes de romper la promesa.
El resultado es un número que puedes defender: "gateamos el p95 de /quote en 200 ms porque es una interacción síncrona, nuestra línea base sana es ~120 ms, y pasados 200 ms el usuario percibe lentitud". Eso es un umbral con criterio. "Le pusimos 200 porque es un número redondo" no lo es.
Errores comunes
Elegir el umbral desde la capacidad del servidor, no desde el usuario. Qué pasa: alguien mide que la app "aguanta hasta 800 ms sin caerse" y pone el umbral en 800. Por qué pasa: se confunde "lo que la máquina puede" con "lo que el usuario tolera". Cómo detectarlo: si justificas tu umbral hablando del servidor y no del usuario, está mal anclado. Cómo corregirlo: el umbral sale del daño al usuario (SLO), no del límite del motor —igual que el límite de velocidad no lo pone el coche—.
Umbral tan holgado que nunca falla. Qué pasa: para evitar builds rojos molestos, alguien pone p(95) < 5000 y el gate siempre pasa. Por qué pasa: se optimiza por no ser molestado, no por proteger al usuario. Cómo detectarlo: si tu gate no ha fallado nunca ni con una regresión real, es teatro. Cómo corregirlo: pon el umbral donde separe bueno de malo de verdad; un gate que no puede fallar no es un gate.
Umbral tan pegado al valor típico que es flaky. Qué pasa: el p95 sano ronda 190 ms y el umbral es 200; el gate falla una de cada tres veces por ruido, y el equipo aprende a re-ejecutar hasta que pase (o a ignorar el rojo). Por qué pasa: no se dejó error budget para la variación normal. Cómo detectarlo: fallos intermitentes sin cambios de código. Cómo corregirlo: sube el umbral hasta que separe regresión de ruido (p. ej. 250–300 ms si el sano es 190 con variación), o estabiliza la medición con más muestras. Un gate flaky se ignora, y un gate ignorado no protege.
Ejercicios
Ejercicio 1 — Clasifica SLI/SLO/SLA. Etiqueta cada enunciado como SLI, SLO o SLA. (a) "El p95 de /quote fue 243 ms en la última corrida." (b) "Nos comprometemos a que el p95 de /quote esté bajo 200 ms el 99% del tiempo." (c) "Si la disponibilidad mensual baja del 99.9%, el cliente recibe un crédito del 10%."
Ver solución
- (a) SLI. Es la métrica cruda medida, un hecho. "Qué mides."
- (b) SLO. Es el SLI + umbral + objetivo, la meta interna que el equipo se compromete a cumplir. "Qué te propones." (Es lo que tu threshold hace ejecutable.)
- (c) SLA. Es un SLO en un contrato comercial, con penalización. "Qué le prometes a un cliente, con consecuencias."
La cadena: mides el SLI, te comprometes con el SLO, le prometes el SLA (normalmente más laxo que el SLO, para tener margen).
Ejercicio 2 — El mismo p95, dos veredictos. Un p95 medido de 243 ms falló contra un umbral de 200 y pasó contra uno de 500. (a) ¿Qué cambió entre las dos corridas: la app, la medición o la regla? (b) ¿Qué demuestra eso sobre la naturaleza del umbral? (c) Si tu usuario percibe lentitud pasados 200 ms, ¿cuál de los dos gates deberías usar, y qué te dice del otro?
Ver solución
- (a) Solo la regla (el umbral: 200 vs 500). La app se comportó igual y la medición fue prácticamente la misma (242.86 vs 243.43 ms, ruido normal).
- (b) Que el umbral es una decisión, no un dato. La medición es objetiva; la aprobación es una elección. El mismo hecho medido es "aprobado" o "reprobado" según el número que tú elegiste.
- (c) El de 200 ms, porque protege lo que a tu usuario le importa (agilidad bajo 200 ms). El de 500 ms sería teatro: dejaría pasar una app que hace esperar 243 ms a 1 de cada 20 usuarios, una degradación que tu propio criterio de usuario considera inaceptable.
Ejercicio 3 — Defiende un umbral. Para una operación de generación de un reporte PDF que el usuario pide y recibe por correo minutos después (no espera en pantalla), propón un umbral de p95 y una o dos frases que lo defiendan desde el usuario/negocio. Compáralo con el de /quote.
Ver solución
Un umbral mucho más holgado, por ejemplo p(95) < 5000 ms (5 s) o incluso más, y probablemente sobre el p95 y no el p99. Defensa: "es un trabajo asíncrono que el usuario no espera en pantalla —lo recibe por correo minutos después—, así que unos segundos de latencia no dañan su experiencia; gatear esta operación en cientos de milisegundos sería malgastar esfuerzo y volver el gate flaky sin beneficio para el usuario". Contraste con /quote: /quote es síncrono (el usuario espera mirando), así que su umbral es estricto (200 ms) porque el daño al usuario empieza pronto; el reporte es asíncrono, así que tolera segundos. Mismo mecanismo de gate, umbrales opuestos, porque el daño al usuario es distinto —exactamente el criterio que la lección 7 aprovecha para poner un SLO por escenario—.
Resumen y siguiente paso
El valor del umbral —el 200 de p(95) < 200— no es una decisión técnica sino de negocio y de usuario: sale del daño que el usuario tolera, no de lo que el servidor puede, igual que el límite de velocidad lo pone el daño de un choque, no el motor del coche. El vocabulario para elegirlo con criterio es el de SRE: el SLI (qué mides, la métrica cruda), el SLO (el SLI + umbral + objetivo, la meta interna —lo que tu threshold hace ejecutable—) y el SLA (un SLO contractual con penalización, normalmente más laxo). El error budget reconoce que la meta no es "siempre" sino un porcentaje, y te recuerda no pegar el umbral al valor típico —eso vuelve el gate flaky—.
Lo viste de forma incontestable: la misma carga y el mismo p95 medido (~243 ms) falló contra un umbral de 200 y pasó contra uno de 500. Nada cambió en la app; cambió la regla que elegimos. Esa es la prueba de que el umbral es una elección que determina qué cuenta como "suficientemente bueno" —y de que el mismo mecanismo es un guardián o un teatro según el criterio con que pusiste el número—.
Antes de avanzar deberías poder: distinguir SLI, SLO y SLA; explicar por qué el umbral sale del usuario y no del servidor; y diagnosticar un gate inútil (demasiado holgado) o flaky (demasiado estricto). Lo que sigue, en la lección 6, es dar un paso atrás y ver que este gate de rendimiento no es único: es el mismo patrón que los coverage gates del ecosistema Testing —una dimensión de calidad vuelta binaria que gatea el pipeline—. Enlazaremos con la guía de testing para ver la familia entera de quality gates a la que este pertenece.
Recursos
- Google SRE Book — Service Level Objectives — el capítulo fundacional sobre SLI, SLO, SLA y cómo se eligen. La fuente del vocabulario de esta lección.
- Google SRE Workbook — Implementing SLOs — el error budget en detalle: cómo se calcula, cómo se gasta y por qué el umbral no es "siempre". Amplía la sección del presupuesto de error.
- Nielsen Norman Group — Response Times: The 3 Important Limits — los puntos de referencia de usabilidad (100 ms = instantáneo, 1 s = mantiene la atención) que anclan el umbral en el usuario. De dónde salen los "200 ms".
- k6 — Thresholds — cómo se declara el umbral elegido en k6; el SLO hecho ejecutable. La regla que esta lección enseña a valorar, no solo a escribir.