Retries de webhooks fiables, con un runbook cuando se agotan

Deja de perder webhooks fallidos. SteadyCron reintenta con backoff exponencial, registra cada intento e incrusta tu runbook en la alerta cuando se agotan los retries.

El problema

Stripe y GitHub reintentan sus webhooks por ti. Casi nada más lo hace. En el momento en que eres tú quien llama a un servicio interno inestable, una API de un partner o el microservicio a medio terminar de un compañero, un solo timeout significa que la llamada desapareció — sin retry, sin registro, sin alerta. Te enteras cuando alguien nota que el efecto esperado nunca ocurrió.

Cómo lo resuelve SteadyCron

  1. 1 Crea un HTTP job con el método, headers y body que tu webhook necesita — incluyendo cualquier header de firma o bearer token.
  2. 2 Configura un timeout y un número de retries con backoff exponencial (y elige si reintentar en timeout o en códigos de estado específicos), para que un 502 o un cold start lento no haga desaparecer la llamada.
  3. 3 Cada intento se registra — código de estado, body de la respuesta, duración — así que "¿el webhook realmente llegó?" tiene una respuesta, no una suposición.
  4. 4 Si los retries se agotan, SteadyCron te alerta — y si has configurado una nota de runbook en el job, la alerta la incrusta directamente (Slack, Telegram, email), para que la solución esté ahí en lugar de enterrada en un documento.
# SteadyCron reintenta esto con backoff y alerta (con tu runbook) si nunca llega:
POST https://internal.example.com/webhooks/order-shipped
Authorization: Bearer ${WEBHOOK_TOKEN}
Content-Type: application/json
app.steadycron.com/jobs

Jobs

New job
Search jobs…
All HTTP Heartbeat
Status Group: env
env:prod 5 jobs 1 failing
weekly-digest-email HTTP 0 9 * * 1 in 2 days 3 days ago
nightly-db-backup Heartbeat 0 2 * * * in 19 h 5 h ago
stripe-reconciliation HTTP 0 */4 * * * in 38 min 3 h ago
cache-warmup HTTP */15 * * * * in 11 min now
search-index-sync Heartbeat */30 * * * * in 6 min 24 min ago
env:dev 3 jobs
seed-test-data HTTP 0 4 * * * in 14 h 10 h ago
preview-env-cleanup Heartbeat 0 */6 * * * in 2 h 4 h ago
trial-expiry-sweep HTTP 0 6 * * * yesterday

Estado, horario y última ejecución de cada job — de un vistazo.

Lo que “retries como servicio” realmente significa aquí

SteadyCron no ejecuta una cola de mensajes genérica. Hace una cosa bien: llamar a un endpoint HTTP según un horario o un disparador, reintentarlo en caso de fallo con backoff, y mantener un registro honesto de lo que pasó. Para llamadas salientes puntuales — reenviar un webhook a un servicio interno, relanzar una integración inestable, disparar una notificación que tiene que llegar — esa es exactamente la tarea:

  • Backoff exponencial, no un bucle de retry plano — un 503 transitorio recibe un retraso creciente en lugar de bombardear el servicio downstream.
  • Retries selectivos — reintenta en timeout, en códigos de estado específicos (p. ej. 502, 503, 429), o solo en errores de red. Tú decides qué es “reintentable” para tu endpoint.
  • Un registro de auditoría real — cada intento es una fila en el registro de ejecuciones con estado, duración y body de respuesta truncado, así que los retries aparecen como intentos separados e inspeccionables en lugar de desaparecer en una caja negra.

Cuando se agotan los retries, no obtienes solo “falló”

Una dead letter queue en el sentido de SQS reproduce mensajes. SteadyCron no intenta ser eso — no es un broker de mensajes. Lo que hace en su lugar es asegurarse de que los retries agotados nunca sean silenciosos: el registro de ejecuciones del job conserva cada intento y su respuesta, y se dispara una alerta en el momento en que falla el último retry.

Esa alerta puede llevar una nota de runbook que escribiste de antemano — “este webhook reenvía a billing-internal; si está caído, revisar primero #billing-incidents” — para que quien reciba la alerta a las 3 de la madrugada no tenga que buscar el contexto.

Encaja bien para

  • Reenviar un webhook de terceros (Stripe, un procesador de pagos, una herramienta de soporte) a un servicio interno que no tiene su propia lógica de retry.
  • Disparar una notificación o efecto secundario que tiene que llegar — aprovisionar un recurso, lanzar un build downstream, sincronizar un registro con otro sistema.
  • Sustituir un bucle de retry artesanal dentro del código de la aplicación, para que la lógica de retry sobreviva a un deploy y aparezca en un solo lugar en vez de estar repartida en bloques try/catch.

Documentación relacionada

Deja de enterarte a las malas

Empieza en el plan gratuito — sin tarjeta de crédito.

Empezar gratis