Saltar al contenido principal
1 oct 2026pruebas carga webhooks

Por Lucas Yoris · Performate

Webhooks bajo fuego: reintentos, idempotencia y verificación de firma a escala

Pruebas de carga de webhooks: reintentos, verificación HMAC, replay en ráfaga—buenas prácticas Stripe y patrones k6 de stress.

Los webhooks fallan bajo carga cuando reintentos duplican trabajo, firmas queman CPU y ráfagas superan la concurrencia de handlers—no cuando entregas sueltas funcionan en Postman. La guía de webhooks de Stripe insiste en claves de idempotencia y handlers tolerantes—tus pruebas deben golpear esa realidad antes de que el proveedor de pagos reintente mil eventos payment.succeeded en tu cluster de staging.

Esta guía modela entrega en ráfaga, replay de event_id duplicado, costo de verificación de firma y enlaza efectos de backlog async (pipelines de cola). Obtienes un script k6 de ráfaga con firma HMAC, enrutamiento de decisión por tipo de riesgo y criterios de aborto cuando suben 5xx o tasas de DLQ.

Escenarios a modelar

El perf de webhooks no es latencia media de POST—es forma y duplicación:

  • Entrega en ráfaga—tormenta de reintentos del proveedor tras que tu endpoint se ralentizó dos minutos.
  • Payloads duplicados con mismo event_id—mismo evento entregado dos veces; el handler debe 200 o 409, no cobrar doble.
  • Ruta de firma inválida—muestra baja tasa de 401/403 para asegurar que fallo crypto es barato vs ruta de éxito.
  • Backlog en cola downstream—handler acepta rápido pero workers van retrasados; HTTP verde, SLO de negocio rojo.
  • Verificación concurrente—HMAC por request a alto RPS CPU-bound en instancias pequeñas.

Forma Stripe vs inbound genérico

Adapta headers (Stripe-Signature, X-Signature custom) a tu proveedor; el patrón k6 se mantiene: firmar body, POST, comprobar códigos idempotentes. Nunca uses secretos de firma de prod en git—solo secretos k6.

k6 ráfaga + eventos duplicados

Ilustrativo—no listo para producción. Incluye escenario de eventos duplicados en plan de prueba extendido; el snippet se centra en ráfaga firmada.

Qué demuestra este ejemplo:

  • Spike ramping-arrival-rate simula tormenta de reintentos—paso 10 → 200 req/s.
  • Firma HMAC en script—modela costo CPU de verificación bajo carga.
  • Check acepta 200 o 409—409 como éxito idempotente para event_id duplicado.
  • Tags route:webhook para filtrar de escenarios REST en la misma suite.
import http from 'k6/http';
import { check, sleep } from 'k6';
import crypto from 'k6/crypto';

const secret = __ENV.WEBHOOK_SECRET || 'test_secret';
const BASE = __ENV.API_BASE || 'https://staging.example.com';

function sign(body) {
  return crypto.hmac('sha256', secret, body, 'hex');
}

export const options = {
  scenarios: {
    webhook_burst: {
      executor: 'ramping-arrival-rate',
      startRate: 10,
      timeUnit: '1s',
      preAllocatedVUs: 30,
      maxVUs: 150,
      stages: [
        { duration: '1m', target: 10 },
        { duration: '30s', target: 200 },
        { duration: '2m', target: 200 },
        { duration: '1m', target: 10 },
      ],
      tags: { suite: 'webhook_burst' },
    },
  },
  thresholds: {
    http_req_failed: ['rate<0.02'],
    'http_req_duration{route:webhook}': ['p(95)<1500'],
  },
};

export default function () {
  const body = JSON.stringify({
    event_id: `evt-${__VU}-${__ITER}`,
    type: 'payment.succeeded',
  });
  const res = http.post(`${BASE}/webhooks/inbound`, body, {
    headers: {
      'Content-Type': 'application/json',
      'X-Signature': sign(body),
    },
    tags: { route: 'webhook', suite: 'webhook_burst' },
  });
  check(res, { accepted: (r) => r.status === 200 || r.status === 409 });
  sleep(0.05);
}

Patrones que funcionan

  • Subconjunto duplicado—10% iteraciones reutilizan lista fija de event_id—valida dimensionado del store de idempotencia.
  • Tripwire de aborto en 5xx > 1% durante ráfaga—para antes de corromper datos de staging compartido.
  • Monitorear DLQ e idempotency DB durante corrida—HTTP es necesario, no suficiente.
  • Solo eventos sintéticos—sin ids de clientes prod en payloads (GDPR).

Antipatrones a evitar

  • Prueba de carga contra URL webhook de prod sin aprobación del proveedor.
  • Medir solo tasa 200—ignorar semántica 409 y efectos secundarios duplicados.
  • Ignorar backlog de workers async—emparejar con lag de cola.
  • Cero fallos de firma en plan de prueba—regresiones crypto se esconden hasta intentos de falsificación en prod.

Pro tip (comando de ejemplo): exportar stats solo webhook para equipo de pagos.

k6 run webhook-burst.js --summary-trend-stats="p(95),p(99)" --tag route=webhook

Qué demuestra este comando: summary filtrado se adjunta a revisión de pagos sin ruido REST de escenarios no relacionados en el mismo repo.

Marco de decisión: riesgo vs prueba

RiesgoPruebaCriterio de pass
Eventos duplicadosRepetir mismo event_id en subconjunto200 o 409; sin efectos secundarios dobles
Tormenta de retrySpike ARRTasa de error + DLQ acotada
FalsificaciónFirmas inválidas baja tasa401 rápido; sin enqueue worker
CPU handlerRáfaga con firma activap95 dentro SLO bajo spike
Lag end-to-endHTTP + tendencia lag colaSLA de negocio en tiempo de completado

Observabilidad y checklist pre-corrida

  • Store de idempotencia dimensionado para duplicados en ráfaga—documentar cardinalidad máxima de event_id probada.
  • Monitoreo DLQ durante prueba con owner de aborto nombrado.
  • Solo eventos sintéticos; secreto de firma desde perfil env.
  • Workers downstream escalados conscientemente—interpretar HTTP vs lag por separado.
  • Comparar ráfaga con lenguaje de spike test en runbook de lanzamiento.
  • Archivar export para pagos/cumplimiento si flujos regulados tocados.

Cómo Performate apoya pruebas de carga de webhooks

Abajo hay un ejemplo de flujo concreto para webhooks inbound de pagos—adapta header de firma a tu proveedor.

Ejemplo: import Postman → escenario ráfaga → export pagos

  1. Importa request webhook desde Postman—plantilla de body preservada. Problema resuelto: payload de firma coincide con lo que pruebas funcionales ya usan.
  2. Añade lógica pre-request de firma en k6 exportado—HMAC desde secreto env. Problema resuelto: ruta crypto incluida sin reimplementación manual cada sprint.
  3. Configura stages de ráfaga en UI—spike 30s a 200 req/s. Problema resuelto: stages visuales reducen errores YAML antes de revisión de pagos.
  4. Corre con tripwire de aborto en 5xx—owner Slack etiquetado. Problema resuelto: staging compartido protegido durante ráfaga agresiva.
  5. Exporta reporte para equipo de pagos—tasa 409 visible junto a 200. Problema resuelto: historia de idempotencia contada con números, no walkthrough de código.
  6. Promueve smoke de entrega única a CI—ráfaga queda manual pre-release. Problema resuelto: regresión diaria en cableado sin tormenta de retry diaria.

Ese flujo mapea directamente al cta de este post: escenarios webhook ejecutables y reportes compartibles sin sprints de glue code.

Cierre

El perf de webhooks es ráfagas + duplicados + crypto, no latencia media de POST. Programa un spike con forma de reintento antes del próximo incidente de pagos; valida rutas 409; vigila DLQ mientras HTTP sigue viéndose bien.

Importa tu webhook inbound, añade firma, corre una ráfaga en staging y registra dónde empiezan los 5xx—esa tasa pertenece al runbook de pagos.

Try Performate free | Book a demo | Webhooks Stripe

¿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 de integración.

← Volver a todas las entradas