webhook-proxy
Uno strato intermedio tra i nostri servizi e i webhook di Discord. Mette in coda gli eventi per destinazione, rispetta i limiti 429 e riprova gli errori 5xx, così le notifiche non si perdono durante i picchi di traffico. Un unico punto attraverso cui passa tutta la comunicazione in uscita.
Un unico punto di uscita per tutta la comunicazione in uscita verso Discord. Mette gli eventi in coda per destinazione, rispetta i limiti 429 con un backoff corretto e riprova gli errori 5xx, invece di perdere notifiche durante un picco di traffico. Il risultato è semplice da enunciare: un evento non svanisce solo perché è capitato un rate limit.
Introduzione
I nostri servizi dicono parecchio su Discord: allarmi di monitoraggio, notifiche di eventi, log operativi. Ciascuno di essi esce tramite un webhook, e i webhook di Discord hanno limiti di frequenza rigidi. Finché il traffico è calmo, nessuno lo sente. Il problema comincia esattamente quando la notifica serve di più - durante un picco, quando più servizi sparano insieme.
webhook-proxy è nato per smettere di appiccicare la gestione dei limiti in ogni servizio separatamente. Invece, tutta la comunicazione in uscita passa per un punto che si assume la consegna: mette in coda, aspetta quando serve, riprova quando ne vale la pena e non perde l'evento per strada. Per i servizi dietro di esso non cambia nulla - inviano come prima.
Il problema che si vede solo sotto carico
Con traffico calmo l'invio ingenuo di un webhook funziona alla perfezione, ed è proprio questo a renderlo insidioso. Il codice spara una richiesta, ottiene un 2xx, va avanti - e nessuno ha motivo di sospettare che qualcosa sia fragile. Fragile è solo il percorso di errore, che con traffico calmo quasi non scatta mai.
Basta un picco per farlo emergere. Più servizi inviano notifiche insieme, colpisci il limite e ottieni un 429, oppure Discord restituisce momentaneamente un 5xx. Nell'approccio ingenuo quell'evento semplicemente sparisce: il codice va avanti, l'eccezione al massimo finisce in un log, e su Discord manca la voce che avrebbe dovuto esserci. Il peggio è che lo perdi proprio al picco di traffico, cioè quando le notifiche contano di più.
Ecco perché il proxy non è un'ottimizzazione di prestazioni. È una garanzia di consegna in condizioni in cui l'invio ingenuo fallisce in silenzio.
ogni webhook ha la propria coda, così una destinazione lenta non blocca le altre.
a un limite il proxy aspetta esattamente quanto dice l'header Retry-After, non a occhio.
un errore del server significa backoff esponenziale e un altro tentativo, non un evento perso.
un payload malformato non diventerà valido al terzo tentativo, quindi non ci sprechiamo tentativi.
Una coda che non blocca il resto
La prima decisione è una coda separata per ogni destinazione. Se tutti gli eventi passassero per un'unica coda condivisa, un solo webhook lento o bloccato fermerebbe la consegna a ogni altro - una destinazione intasata e silenzio ovunque. Separare le code fa sì che un problema con un webhook resti con quel webhook.
La stessa struttura dà resilienza ai picchi. Quando arriva un'ondata, gli eventi non vengono persi - atterrano nella coda della loro destinazione e aspettano una finestra in cui il limite si allenta. Da fuori sembra un ritardo momentaneo invece di una perdita, ed è una qualità del tutto diversa: una notifica ritardata svolge ancora il suo compito, una persa non ne svolge nessuno.
Il cuore: il ciclo di consegna
Tutta la logica si riduce a una decisione per risposta: il successo la conclude, 429 dice aspetta, 5xx dice riprova, altri 4xx significano fermarsi senza riprovare. Distinguere questi casi è la differenza tra un proxy che consegna e uno che o perde eventi o macina all'infinito su un payload rotto.
Asimmetria: 429 contro 5xx
La chiave è l'asimmetria tra 429 e 5xx. Su un 429 è Discord stesso a dire quanto aspettare - lo leggiamo dall'header e aspettiamo esattamente quello, né meno né più. Su un 5xx nessuno dice nulla, quindi aggiungiamo un backoff esponenziale per non martellare un server momentaneamente caduto con una raffica di ritentativi immediati.
L'errore più comune è riprovare tutto alla cieca. Su un 429 un ritentativo ha senso, ma su un 400 o un 404 no: il payload non si aggiusta da solo, e non fai che raggiungere il limite più in fretta e macinare all'infinito su qualcosa che non passerà mai. Riprova ciò che è transitorio, e solo quello. Il resto dovrebbe fallire subito, rumorosamente e una volta sola.
L'effetto: un picco che l'altra parte non vede mai
Per i servizi dietro di esso il proxy è invisibile - inviano esattamente come prima e non sanno nulla di limiti o ritentativi. Tutta quella complessità sta in un solo posto invece di essere spalmata su ogni servizio separatamente. Significa anche che una correzione nella gestione dei limiti si fa una volta, non in più basi di codice insieme.
Cosa fa il proxy con una risposta (a titolo illustrativo)
La differenza si vede solo alla prossima ondata di traffico, ed è tutto il punto. Le notifiche non svaniscono in silenzio nel momento in cui servono di più - aspettano in coda e arrivano appena il limite si allenta. Un punto di uscita ha trasformato la perdita silenziosa di eventi in un ritardo al massimo momentaneo, ed è tutta la differenza tra un monitoraggio di cui ci si può fidare e uno che tace proprio quando scoppia l'incendio.
Altri progetti
Altri lavori della stessa categoria - scopri come affrontiamo sfide simili.
Hai un progetto simile?
Contattaci - il preventivo è gratuito e arriva entro un'ora.



