
Un 429 Too Many Requests è l’unico codice di stato che riguarda voi e non il server o la cosa che avete chiesto. Non si è rotto niente, non manca niente, e avete il permesso di stare qui. Avete semplicemente chiesto più spesso di quanto qualcuno abbia ritenuto ragionevole, e la risposta è un rifiuto con un orologio attaccato.
Tutto il resto nella fascia 4xx descrive una singola richiesta: questa era malformata, questa non aveva credenziali, questa non nominava nulla. Un 429 descrive uno schema. È il server che parla del vostro comportamento lungo una finestra di tempo, ed è per questo che può arrivare in risposta a una richiesta perfettamente corretta che dieci minuti fa avrebbe funzionato.
L’unico errore in cui riprovare peggiora le cose
La maggior parte degli errori premia un nuovo tentativo. Un 503 spesso si risolve al secondo colpo, e con un 500 vale la pena un ricaricamento nel caso abbiate beccato un brutto momento. L’istinto di solito ha ragione, e qui ha esattamente torto.
Un rate limiter conta le richieste. Un nuovo tentativo è una richiesta. Martellare un servizio che vi ha appena detto di rallentare allunga la finestra in cui vi sta trattenendo e, sui servizi che scalano la pena, trasforma un limite di sessanta secondi in un’ora o in un blocco che qualcuno deve togliere a mano. Il ciclo di retry ingenuo, quello senza pausa dentro, è il modo in cui un breve rallentamento diventa un disservizio che sembra colpa dell’altra parte.
Quindi un 429 è l’errore in cui non fare niente è la scelta attiva. Aspettate che la finestra passi, poi riprovate, una volta.
Gli header che dicono quando tornare
Un 429 di solito porta Retry-After, che dà o un numero di secondi o una data:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1789412400
Retry-After è quello standard e l’unico su cui potete contare. La famiglia X-RateLimit-* è una
convenzione e non una specifica: molto usata, scritta in modi diversi da servizi diversi, e da
leggere quando c’è, perché vi dice la forma del limite e non solo il prossimo momento in cui
potete bussare.
Quegli header sono la differenza tra arretrare correttamente e tirare a indovinare. Se state scrivendo qualcosa che parla con un’API a intervalli, leggeteli: a un servizio che ha detto sessanta secondi e riceve un tentativo al secondo si sta chiedendo centoventi volte di servire richieste che ha già rifiutato.
Quando il traffico non era vostro
La parte scomoda di un 429 è che la cosa contata raramente è una persona. È un indirizzo IP, una chiave API, un account o una sessione, e ognuna di queste copre più di uno di voi.
Un ufficio dietro un solo indirizzo, un bar, un operatore mobile che fa carrier-grade NAT, una pipeline di CI che condivide una chiave con un team, un collega che prova uno script sullo stesso endpoint con le stesse credenziali. Tutto questo produce un 429 per qualcuno che non ha fatto nulla di insolito, e niente di tutto ciò è visibile dalla pagina di errore.
Da qui il test utile. Se un 429 vi segue tra reti diverse è il vostro account o la vostra chiave, e se sparisce sotto rete mobile era l’indirizzo da cui arrivavate. È la stessa domanda del distinguere il vostro bug dal loro disservizio, posta su un limite invece che su un guasto.
Potete essere limitati senza vedere mai un 429
Niente obbliga un servizio a usare questo codice. Molti restituiscono un 403 per far sembrare la limitazione una decisione sui permessi, alcuni restituiscono un 503 perché da fuori “non adesso” è vero comunque, e una CDN davanti a un’applicazione risponderà spesso con la propria scelta invece che con quella dell’applicazione.
Quindi un 429 è in un certo senso una buona notizia: è un servizio che è specifico con voi. La sua assenza non è prova che non vi stiano limitando, e se un 403 o un 503 compare solo sotto carico e solo da un indirizzo, un limiter è la cosa da sospettare qualunque cosa dica il codice.
Se l’API è vostra
La domanda a cui rispondere prima di qualsiasi messa a punto è quale strato stia contando. Un limite nella vostra applicazione, uno in nginx e uno alla CDN sono tre insiemi di numeri diversi, e quello contro cui sbattono i vostri utenti di solito non è quello che state guardando.
Poi mandate gli header. Un 429 senza Retry-After è un servizio che si rifiuta di dire quando, e
lascia a ogni client il compito di inventarsi un backoff, e quelli che si inventano sono peggiori
del numero che gli avreste dato voi. Essere specifici non costa nulla.
E fate attenzione a cosa conta il limite. I limiti per IP puniscono uffici e reti condivise per il comportamento di una sola persona che ci sta dentro, ed è un ticket di supporto che arriva come “il vostro sito è rotto per tutto il nostro team”. I limiti per account o per chiave sono più difficili da implementare e molto più facili da spiegare.
Perché un 429 è difficile da ricostruire dopo
Quando qualcuno ve ne parla, la finestra è passata e la richiesta funziona. Ciò che l’ha fatta fallire non era la richiesta ma la sua compagnia: le altre novantanove arrivate nello stesso minuto, la maggior parte da qualcun altro, nessuna delle quali ora è davanti a voi.
Session Replay
Estensione Chrome gratuita. Un clic sulla pagina che si comporta male cattura lo screenshot, la console e il log di rete, e vi dà un link da incollare nel ticket.
Il log di rete è ciò che rende un 429 indagabile: la richiesta fallita, il minuto esatto, e gli header di risposta che dicono quale limite è stato toccato e quanto gli restava da correre. È la differenza tra una segnalazione che qualcuno può confrontare con il log di un rate limiter e un messaggio che dice che stamattina il sito ha smesso di funzionare per un po’.
In un paragrafo
Un 429 Too Many Requests significa che avete chiesto troppo spesso, il che lo rende l’unico codice
di stato che riguarda il vostro comportamento invece del server o della risorsa. È anche l’unico
errore in cui riprovare è attivamente controproducente, perché un nuovo tentativo è un’altra
richiesta che il limiter conta: leggete Retry-After, aspettate, poi andate una volta. Il
traffico contato spesso non è il vostro, dato che i limiti si applicano a indirizzi e chiavi che
coprono interi uffici e team, e un telefono in rete mobile vi dirà con quale dei due avete a che
fare. Se l’API è vostra, stabilite quale strato conta, mandate sempre Retry-After, e preferite
limitare una chiave invece di un indirizzo, così che una persona non possa chiudere fuori un
intero edificio.