Skip to main content
9 jul 2026limites tasa throttling api k6

Por Performate

Pruebas de rate limits y throttling: cómo validar comportamiento 429 con seguridad

Ejercita Retry-After y headers de cuota en staging, modela backoff con honestidad y demuestra que tus clientes degradan con gracia.

Tu cliente móvil reintenta al instante en cada 429—y staging nunca demostró que no amplificaría un throttle breve del gateway en tormenta de reintentos. Disparar 429 Too Many Requests a propósito en production es negligente; demostrar comportamiento en staging con límites realistas es ingeniería. Las pruebas de carga de rate-limit responden otra pregunta que gráficos de RPS pico: cuando actúan las cuotas, ¿los clientes hacen backoff, mienten los headers y el sistema se recupera limpio?

Validar throttling con k6 implica rampar tráfico hasta que activen límites mientras asertas Retry-After, headers de cuota y paths de degradación del cliente—no celebrar promedios HTTP 200 mientras 429s se esconden en colas sin tags. En esta guía verás cómo diseñar escenarios seguros en staging, qué métricas importan más allá de tasas de éxito y cómo exportar evidencia para revisiones de compliance.

Por qué los rate limits cambian el rendimiento—no solo códigos de estado

Bajo presión de cuota, latencia y semántica de fallo divergen de pruebas de carga en steady state:

  • Timing de onset 429 revela límites mal configurados mucho antes de que tráfico real los golpee.
  • Headers Retry-After gobiernan sleep del cliente; ignorarlos produce thundering herds.
  • Cuotas por key vs por IP hacen que el mismo RPS de un tenant se comporte distinto que keys distribuidas.
  • Saturación downstream puede imitar throttling—iteration_duration en alza con límites idle apunta al cuello de botella equivocado.

Piensa en rate limits como un parking con cartel de capacidad fija. Probar solo «qué tan rápido entran autos» omite si el cartel lleno dispara colas ordenadas o giros en U caóticos.

Coordina con owners de API sobre tenants sintéticos: nunca martilles vendors terceros sin contratos (dependencias de terceros).

Implementación práctica en k6: ramp hasta 429, asertar headers

Modela un ramp por etapas que cruce umbrales de cuota documentados. Etiqueta iteraciones por client_profile para que resúmenes separen flujos móvil, batch y partner.

Script de ejemplo (ilustrativo—no es una prueba lista para producción). Adapta base URL, keys, cuotas y backoff a tu entorno.

Qué demuestra este ejemplo:

  • Ramping arrival rate cruza un límite ficticio de 60 req/min por key en etapas controladas.
  • Métricas custom cuentan respuestas 429 y registran valores observados de Retry-After.
  • Simulación de backoff del cliente: sleep respeta segundos del header en lugar de reintento instantáneo.
  • Checks en headers de cuota: X-RateLimit-Remaining baja de forma predecible cerca del umbral.
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Counter, Trend } from 'k6/metrics';

const BASE = __ENV.API_BASE || 'https://staging.example.com';
const rateLimited = new Counter('rate_limited_429');
const retryAfterSec = new Trend('retry_after_seconds');

export const options = {
  scenarios: {
    ramp_to_quota: {
      executor: 'ramping-arrival-rate',
      startRate: 10,
      timeUnit: '1m',
      preAllocatedVUs: 20,
      maxVUs: 80,
      stages: [
        { duration: '3m', target: 30 },
        { duration: '3m', target: 60 },
        { duration: '3m', target: 90 },
        { duration: '2m', target: 30 },
      ],
      tags: { client_profile: 'mobile-app', route: 'search' },
      exec: 'searchRequest',
    },
  },
  thresholds: {
    rate_limited_429: ['count>0'],
    'http_req_failed{status:429}': ['rate<0.5'],
    http_req_failed: ['rate<0.05'],
  },
};

export function searchRequest() {
  const res = http.get(`${BASE}/v1/search?q=load-test`, {
    headers: { Authorization: `Bearer ${__ENV.API_KEY}` },
    tags: { client_profile: 'mobile-app', route: 'search' },
  });

  if (res.status === 429) {
    rateLimited.add(1);
    const ra = res.headers['Retry-After'];
    if (ra) {
      const seconds = Number(ra);
      retryAfterSec.add(seconds);
      sleep(seconds);
    } else {
      sleep(1);
    }
    return;
  }

  check(res, {
    'search 2xx': (r) => r.status >= 200 && r.status < 300,
    'remaining header present': (r) => r.headers['X-RateLimit-Remaining'] !== undefined,
  });
  sleep(0.2);
}

Patrones que funcionan

  • Refleja cuotas documentadas (por minuto / por key / por IP) desde docs del proveedor—la guía IETF evoluciona; valida contra tu gateway (HTTP requests).
  • Etiqueta por client_profile para que lógica de retry móvil no enmascare jobs batch (metrics).
  • Corre etapa de recuperación tras el ramp—vigila http_req_failed después de reset de allowance.
  • Compara con análisis de cuellos de botella cuando iteration_duration sube y conteos 429 se mantienen planos.

Antipatrones a evitar

  • Martillar production o APIs de vendors sin aprobación escrita y keys sintéticas.
  • Loguear bodies completos que puedan contener PII al capturar payloads 429.
  • Tratar cualquier 429 como fallo sin distinguir ejercicio esperado de cuota de misconfiguración.

Pro tip (comando de ejemplo): muestra tendencias 429 por separado en el resumen.

k6 run rate-limit-ramp.js --summary-trend-stats="count,avg" --tag client_profile=mobile-app

Qué demuestra este comando: resúmenes etiquetados permiten a revisores de compliance ver cuándo actuaron límites y cómo se comportó Retry-After entre etapas.

Marco de decisión: prueba de cuota vs RPS pico vs soak

SituaciónAcción recomendada
Reglas nuevas de rate en gateway o WAFRamp por etapas en staging; aserta onset 429 cerca del umbral documentado
Cliente móvil publica lógica de retryEscenario con sleep honesto en Retry-After; mide decaimiento de tormenta
Job batch comparte key con tráfico interactivoEscenarios separados tag client_profile:batch vs mobile-app
API tercera con tier contractualSolo tenant sintético; nunca exceder cuota de prueba acordada
Carga steady ya en verdeAñade etapa que cruce cuota—RPS pico solo oculta comportamiento throttle

Usa ramp que cruce cuota si necesitas demostrar que clientes y gateways se comportan cuando actúan límites—no solo antes.

Usa pruebas de RPS pico si la pregunta es saturación bajo cuota (pools, CPU, DB)—complementarias, no sustituto.

Usa soak post-throttle si debes probar recuperación tras reset de allowances—tormentas de retry suelen aparecer en el segundo minuto, no en el primer pico.

Checklist pre-export para compliance y equipos cliente

Antes de compartir evidencia de rate-limit:

  • Tenant sintético y API key documentados; nunca keys de production.
  • Umbrales de cuota documentados citados en notas (por minuto / key / IP).
  • Tasa de onset 429 y etapa registradas—no solo porcentaje agregado de éxito.
  • Distribución de Retry-After capturada (métrica custom o muestra de log sin PII).
  • Path de backoff del cliente ejercitado—sin bucles instant-retry en script salvo probar mal comportamiento explícitamente.
  • Etapa de recuperación muestra http_req_failed asentándose tras reset de allowance.
  • APIs terceras probadas solo con aprobación del owner y referencia contractual.

Cómo Performate simplifica orquestación de escenarios rate-limit

Editar scripts a mano hace doloroso el tuning de cuotas. Abajo un ejemplo de flujo concreto para el ramp de search API de este artículo.

Ejemplo: escenificar prueba que cruza cuota sin quemar allowances de production

  1. Importa la colección con peticiones search (o partner) y auth ya configurada. Problema resuelto: mismas URLs que QA—sin endpoints misteriosos en pruebas throttle.
  2. Crea escenario ramping-arrival-rate en el editor visual: 30 → 60 → 90 req/min en etapas alineadas a cuota documentada. Problema resuelto: cruce honesto de límites sin editar arrays de stages cada pasada.
  3. Aplica tags: client_profile:mobile-app, route:search. Problema resuelto: resúmenes separan flujos cuando batch y móvil comparten infra.
  4. Corre en staging y filtra el reporte por respuestas 429 y latencia en recuperación. Problema resuelto: revisores ven timing de onset, no un pass/fail verde único.
  5. Duplica el escenario para client_profile:batch con otra key—compara si jobs batch roban cuota interactiva. Problema resuelto: comportamiento por tenant visible sin bifurcar scripts.
  6. Exporta script k6 y resumen para adjuntar a tickets de release o revisión con vendor. Problema resuelto: la prueba viaja con el change request.

Ese flujo encaja con el cta de este post: orquestar escenarios rate-limit por etapas sin quemar cuotas de production.

Cierre

La confianza en rate-limit es un problema de degradación, no un trofeo de RPS pico. Rampa hasta que activen 429s en staging, respeta Retry-After en tu script, etiqueta perfiles cliente y demuestra recuperación tras reset de allowances.

Corre el ramp de staging de esta semana contra tu cuota documentada—y anota si el onset 429 coincide con el contrato o señala misconfiguración que tu prueba de pico nunca alcanzó.

Try Performate free | Book a demo | k6 checks

¿Listo para optimizar el rendimiento de tu API?

Usa Performate para orquestar escenarios de rate-limit por etapas sin quemar cuotas de producción.

← Volver a todas las entradas