webhook-proxy
Una capa intermedia entre nuestros servicios y los webhooks de Discord. Encola los eventos por destino, respeta los límites 429 y reintenta los errores 5xx, de modo que las notificaciones no se pierden en los picos de tráfico. Un único punto por el que pasa toda la comunicación saliente.
Un único punto de salida para toda la comunicación saliente hacia Discord. Encola los eventos por destino, respeta los límites 429 con un backoff correcto y reintenta los errores 5xx, en lugar de perder notificaciones durante un pico de tráfico. El resultado es fácil de enunciar: un evento no desaparece solo porque haya llegado un límite de tasa.
Introducción
Nuestros servicios hablan bastante en Discord: alarmas de monitorización, notificaciones de eventos, registros operativos. Cada uno de ellos sale por un webhook, y los webhooks de Discord tienen límites de tasa estrictos. Mientras el tráfico es tranquilo, nadie lo nota. El problema empieza exactamente cuando la notificación es más necesaria - durante un pico, cuando varios servicios disparan a la vez.
webhook-proxy nació para dejar de pegar la gestión de límites en cada servicio por separado. En su lugar, toda la comunicación saliente pasa por un punto que asume la entrega: encola, espera cuando hace falta, reintenta cuando merece la pena y no pierde el evento por el camino. Para los servicios detrás de él no cambia nada - envían como antes.
El problema que solo se ve bajo carga
Con tráfico tranquilo el envío ingenuo de un webhook funciona a la perfección, y eso es justo lo que lo hace traicionero. El código dispara una petición, obtiene un 2xx, sigue adelante - y nadie tiene motivo para sospechar que algo sea frágil. Lo frágil es solo el camino de error, que con tráfico tranquilo casi nunca se dispara.
Basta un pico para sacarlo a la luz. Varios servicios envían notificaciones a la vez, alcanzas el límite y obtienes un 429, o Discord devuelve momentáneamente un 5xx. En el enfoque ingenuo ese evento simplemente desaparece: el código sigue adelante, la excepción como mucho aterriza en un registro, y en Discord falta la entrada que debía estar ahí. Lo peor es que lo pierdes precisamente en el pico de tráfico, es decir, cuando las notificaciones importan más.
Por eso el proxy no es una optimización de rendimiento. Es una garantía de entrega en condiciones en las que el envío ingenuo falla en silencio.
cada webhook tiene su propia cola, de modo que un destino lento no bloquea a los demás.
ante un límite el proxy espera exactamente lo que dice la cabecera Retry-After, no a ojo.
un error de servidor significa backoff exponencial y otro intento, no un evento perdido.
un payload malformado no se volverá válido al tercer intento, así que no malgastamos intentos en él.
Una cola que no bloquea al resto
La primera decisión es una cola separada para cada destino. Si todos los eventos pasaran por una única cola compartida, un solo webhook lento o bloqueado detendría la entrega a todos los demás - un destino atascado y silencio en todas partes. Separar las colas hace que un problema con un webhook se quede con ese webhook.
La misma estructura da resiliencia ante picos. Cuando llega una oleada, los eventos no se pierden - aterrizan en la cola de su destino y esperan una ventana en la que el límite afloja. Desde fuera parece un retraso momentáneo en vez de una pérdida, y es una calidad completamente distinta: una notificación retrasada sigue cumpliendo su función, una perdida no cumple ninguna.
El corazón: el bucle de entrega
Toda la lógica se reduce a una decisión por respuesta: el éxito la termina, 429 dice espera, 5xx dice reintenta, otro 4xx significa parar sin reintentar. Distinguir esos casos es la diferencia entre un proxy que entrega y uno que o pierde eventos o muele sin fin sobre un payload roto.
Asimetría: 429 frente a 5xx
La clave es la asimetría entre 429 y 5xx. En un 429 Discord mismo dice cuánto esperar - lo leemos de la cabecera y esperamos exactamente eso, ni menos ni más. En un 5xx nadie dice nada, así que añadimos un backoff exponencial para no aporrear a un servidor momentáneamente caído con una ráfaga de reintentos inmediatos.
El error más común es reintentar todo a ciegas. En un 429 un reintento tiene sentido, pero en un 400 o un 404 no: el payload no se arreglará solo, y solo alcanzas el límite más rápido y mueles sin fin sobre algo que nunca pasará. Reintenta lo que es transitorio, y solo eso. El resto debería fallar de inmediato, en voz alta y una sola vez.
El efecto: un pico que el otro lado nunca ve
Para los servicios detrás de él el proxy es invisible - envían exactamente como antes y no saben nada de límites ni reintentos. Toda esa complejidad está en un solo lugar en vez de estar untada por cada servicio por separado. También significa que una corrección en la gestión de límites se hace una vez, no en varias bases de código a la vez.
Qué hace el proxy con una respuesta (ilustrativo)
La diferencia solo se ve en la siguiente oleada de tráfico, y ese es todo el sentido. Las notificaciones no desaparecen en silencio en el momento en que son más necesarias - esperan en la cola y llegan en cuanto el límite afloja. Un punto de salida convirtió la pérdida silenciosa de eventos en, como mucho, un retraso momentáneo, y esa es toda la diferencia entre una monitorización en la que se puede confiar y una que se calla justo cuando empieza el fuego.
Más proyectos
Más trabajos de la misma categoría - mira cómo abordamos retos parecidos.
¿Tiene un proyecto similar?
Escríbenos - el presupuesto es gratuito y llega en una hora.



