Por Lucas Yoris · Performate
Ramping arrival rate vs modelos open vs closed: elegir un ejecutor para APIs
Ejecutores ramping arrival-rate en k6: cargas open vs closed, maxVUs, iteraciones descartadas—docs de ejecutores Grafana para modelos de tráfico API.
Tu dashboard de producción muestra 120 req/s estables en el endpoint de búsqueda, pero la prueba de carga usa 200 VUs en loop sin pausa. El informe dice «pasa», el capacity planning extrapola 200 sesiones concurrentes, y el lanzamiento del Black Friday descubre que la cola real era de llegadas por segundo, no de usuarios logueados esperando.
Los ejecutores de k6 codifican modelos de carga cerrada vs abierta—y elegir mal produce números que parecen ciertos pero no escalan a decisiones de infraestructura. En esta guía verás por qué ramping-arrival-rate modela APIs públicas distinto de ramping-vus, cómo interpretar iteraciones descartadas, y qué señales deberían cambiar tu executor antes de presentar resultados a platform.
Por qué el modelo de carga cambia la capacidad—no solo el gráfico
A nivel intuitivo, «más VUs = más carga». Bajo la superficie, el executor define qué variable controlas:
- Carga cerrada (
constant-vus,ramping-vus) — fijas usuarios concurrentes que iteran en loop. Ideal cuando la concurrencia refleja sesiones logueadas con think time entre acciones. - Carga abierta (
constant-arrival-rate,ramping-arrival-rate) — fijas iteraciones (o requests) por unidad de tiempo. Ideal cuando las peticiones llegan independientes del tiempo que el cliente tarde en responder—APIs públicas, colas, webhooks. - Iteraciones descartadas — cuando el arrival rate supera el throughput alcanzable, k6 no puede completar iteraciones a tiempo; subir
maxVUso relajar objetivos (arrival-rate tracking).
Piensa en un restaurante: VUs fijos son mesas ocupadas todo el rato; arrival rate es clientes que entran a un ritmo fijo aunque el servicio se relentice.
Cuando VUs fijos mienten sobre APIs abiertas
Las pruebas con 50 VUs en loop pueden generar más req/s cuando la API responde rápido y menos cuando se degrada—el opuesto de una cola de producción con tasa de llegada constante. Eso distorsiona cuántos VUs necesitas y invalida comparaciones entre builds. Combina el executor correcto con tipos de escenario para que la forma de tráfico coincida con la pregunta.
Implementación práctica con k6: ramping-arrival-rate con stages
Modela un pico de tráfico gradual—como un evento de marketing o apertura de ventas—con stages que suben la tasa de llegada y luego la mantienen. Vigila dropped_iterations en el summary.
Script de ejemplo (ilustrativo—no es una prueba lista para producción). El snippet usa URLs, tokens y tasas ficticias. Adapta base URL, auth y stages a tu entorno.
Qué demuestra este ejemplo:
- Modelo abierto honesto:
ramping-arrival-rateapunta a 80 req/s en plateau, no a «N usuarios martillando». - Rampa gradual: stages de 20→50→80 req/s evitan el shock instantáneo que oculta autoscaling.
- Headroom de VUs:
preAllocatedVUsymaxVUsaltos reducen iteraciones descartadas cuando la API se degrada. - Umbrales de saturación: alerta explícita si
dropped_iterationssupera cero—señal de que el objetivo de tasa no es alcanzable.
import http from 'k6/http';
import { check, sleep } from 'k6';
const BASE = __ENV.API_BASE || 'https://staging.example.com';
export const options = {
scenarios: {
search_open_load: {
executor: 'ramping-arrival-rate',
startRate: 0,
timeUnit: '1s',
preAllocatedVUs: 50,
maxVUs: 200,
stages: [
{ duration: '2m', target: 20 }, // calentamiento
{ duration: '3m', target: 50 }, // tráfico normal
{ duration: '5m', target: 80 }, // pico de campaña
{ duration: '2m', target: 80 }, // plateau
{ duration: '2m', target: 0 }, // ramp-down
],
exec: 'search',
tags: { route: 'search' },
},
},
thresholds: {
http_req_duration: ['p(95)<400', 'p(99)<800'],
http_req_failed: ['rate<0.01'],
dropped_iterations: ['count==0'],
},
};
export function search() {
const res = http.get(`${BASE}/v1/search?q=k6+load+testing`, {
headers: { Authorization: `Bearer ${__ENV.TOKEN}` },
tags: { route: 'search' },
});
check(res, { 'search 2xx': (r) => r.status >= 200 && r.status < 300 });
sleep(0.1);
}
Patrones que funcionan
ramping-arrival-ratepara picos — sube tasa gradualmente; observa p95 vs p99 en cada stage (executors reference).constant-arrival-ratepara línea base — tasa fija cuando prod es estable y necesitas regresión repetible.ramping-vuspara sesiones — cuando modelas usuarios logueados con think time entre pasos de un flujo multipaso.- Stages vía entorno — serializa targets en
__ENVpara que CI reproduzca la misma rampa con distintos techos.
Anti-patrones a evitar
- Usar
ramping-vuspara una API pública sin think time y extrapolar req/s a producción. - Ignorar
dropped_iterations—significa que tu tasa objetivo no se cumplió, no que la API aguantó. maxVUsdemasiado bajo—k6 descarta iteraciones en lugar de backpressure realista.
Tip pro (comando de ejemplo):
k6 run search-ramping.js --summary-trend-stats="p(95),p(99),count"
Qué demuestra este comando: el summary incluye conteos de iteraciones descartadas junto a percentiles—útil para demostrar en revisiones de capacidad si el objetivo de tasa fue alcanzable.
Marco de decisión: closed vs open vs ramping
| Situación | Acción recomendada |
|---|---|
| API pública, cola, webhook—llegadas independientes del response time | constant-arrival-rate o ramping-arrival-rate |
| App con login, carrito, sesión—concurrencia = usuarios activos | constant-vus o ramping-vus + think time |
| Evento con pico gradual (lanzamiento, campaña) | ramping-arrival-rate con stages y plateau |
| Smoke en CI—validación rápida de salud | shared-iterations o arrival rate bajo (CI/CD) |
| Comparar builds con misma presión absoluta | Mismo executor y misma tasa objetivo—not solo mismos VUs |
Usa arrival rate si production metrics reportan req/s o iteraciones/s como variable principal.
Usa VUs fijos si analytics de producto habla de «usuarios concurrentes» o sesiones activas con pacing humano.
Usa ramping si necesitas observar autoscaling, warm-up de caché o colas bajo presión creciente—not solo un snapshot estático.
Observabilidad, documentación y siguientes pasos
Las pruebas con executors mal elegidos solo sirven si documentas qué modelaste. Antes de presentar resultados:
- Registra executor, tasa objetivo (o VUs), stages y valor de
maxVUsen el reporte de la corrida. - Incluye
dropped_iterationsen el criterio de pass/fail cuando uses arrival rate. - Correlaciona req/s de k6 con métricas del load balancer—detecta desalineación de modelo.
- Archiva JSON de escenario y git SHA por release para comparar regresiones con criterio.
- Revalida el modelo trimestralmente cuando el producto pasa de «beta cerrada» a API pública.
Cómo Performate simplifica el cambio de executor sin reescribir scripts
Alternar entre VUs y arrival rate en scripts crudos obliga a editar bloques options a mano. Abajo hay un ejemplo concreto de flujo para el endpoint de búsqueda de arriba—adapta tasas y stages a tu analytics.
Ejemplo: pasar de smoke con VUs a rampa open-model en un solo workspace
- Importa el request de búsqueda desde Postman u OpenAPI. Problema resuelto: el flujo HTTP vive una vez; el executor es un knob, no un fork de script.
- Crea un escenario smoke con pocos VUs y duración corta para CI. Problema resuelto: validación rápida sin confundir smoke con capacity test.
- Duplica el escenario y cambia el executor a ramping arrival rate—20→50→80 req/s en el editor visual. Problema resuelto: misma petición, modelo distinto, sin copiar carpetas.
- Ajusta
maxVUsen el panel y observa si el reporte muestra iteraciones descartadas. Problema resuelto: headroom visible para platform sin parsear logs de k6. - Compara reportes smoke vs rampa en la vista lado a lado—filtra por
route:search. Problema resuelto: QA y backend ven la misma petición bajo dos modelos en un export. - Exporta el script k6 con el executor elegido para nightly gates (pruebas de carga en CI/CD).
Ese flujo conecta directo con el cta de este post: descubrir el modelo correcto sin reescribir scripts enteros cada iteración.
Cierre
El riesgo de capacity planning es un problema de modelo, no solo de magnitud. Elige executors que reflejen cómo llega el tráfico en prod—arrival rate para colas abiertas, VUs para sesiones—and trata las iteraciones descartadas como señal de saturación del generador o del sistema bajo prueba.
Corre una rampa con ramping-arrival-rate contra staging esta semana antes de tu próxima estimación de infraestructura—y anota si el plateau de 80 req/s se sostuvo sin drops.
¿Listo para optimizar el rendimiento de tu API?
Usa Performate para convertir este playbook en escenarios k6 ejecutables, umbrales y reportes compartibles sin perder días en código pegamento.