429 Too Many Requests significa che il server ti sta applicando un rate limit: il client ha inviato in un certo intervallo più richieste di quelle consentite dal server e dovrebbe aspettare prima di riprovare. Non c’è niente di rotto, e ripetere subito la richiesta peggiora le cose. Un server ben fatto indica quanto aspettare in un header Retry-After; un client ben fatto aspetta almeno quel tempo e, in sua assenza, fa backoff con ritardi crescenti. Quando un monitor riceve un 429, la soluzione abituale è escluderlo dal limite o controllare un endpoint che non ne ha.
Come funziona il rate limiting
L’RFC 6585 definisce il 429 ma lascia le regole a ciascun server. Un limite ha tre componenti:
Chi viene conteggiato: un indirizzo IP, una chiave API, un account utente o una combinazione. I limiti per IP contano insieme tutti quelli che stanno dietro lo stesso indirizzo.
Cosa viene conteggiato: tutte le richieste o solo alcune, come login, ricerche o un endpoint API costoso, spesso con un limite più severo.
Come viene conteggiato il tempo: una finestra fissa si azzera allo scoccare del minuto; una finestra mobile guarda gli ultimi 60 secondi; un token bucket si ricarica a ritmo costante e consente brevi picchi fino alla sua capienza.
Spesso la risposta ti dice a che punto sei:
HTTP/2 429
retry-after: 30
x-ratelimit-limit: 100
x-ratelimit-remaining: 0
x-ratelimit-reset: 1793091600
Retry-After è standard e contiene un numero di secondi oppure una data HTTP. Gli header X-RateLimit-* sono una convenzione diffusa più che uno standard, e il loro significato varia: reset può essere un timestamp Unix o un numero di secondi, quindi leggi la documentazione dell’API. Una bozza IETF definisce i campi standard RateLimit e RateLimit-Policy, che alcune API hanno iniziato a inviare.
Da dove arrivano i 429
API di terze parti che chiami, come servizi di pagamento, email, mappe o chat, che limitano ogni chiave o account.
Il tuo API gateway o framework, tramite un middleware di rate limiting.
Il tuo web server. limit_req di nginx risponde 503 per impostazione predefinita; imposta limit_req_status 429 così i client sanno che devono rallentare invece di pensare a un downtime.
CDN e WAF, tramite regole di rate limiting. A seconda della regola, la risposta è un 429, un 403 o una pagina di verifica.
Protezione di login e moduli in un CMS o in un plugin di sicurezza, che limita i tentativi per indirizzo.
Gestire un 429 lato client
Rispetta Retry-After. Aspetta almeno quanto indica. Riprovare prima di solito porta a un altro 429 e può prolungare un blocco.
Fai backoff esponenziale, con jitter. Senza Retry-After, aspetta di più dopo ogni errore, per esempio 1, 2, 4 e 8 secondi, più una componente casuale, così molti client non riprovano nello stesso istante.
Limita i tentativi. Dopo qualche tentativo, arrenditi e segnala l’errore, oppure metti il lavoro in coda per dopo.
Invia meno richieste. Metti in cache le risposte, usa endpoint batch, chiedi pagine più grandi e usa i webhook invece del polling dove l’API li offre.
Distribuisci il lavoro pianificato. I cron job che partono tutti allo scoccare dell’ora raggiungono i limiti insieme; sfasali di qualche minuto. La guida alle espressioni cron mostra come.
async function fetchWithBackoff(url, options = {}, attempts = 5) {
for (let attempt = 0; attempt < attempts; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429) return response;
const retryAfter = Number(response.headers.get(‘retry-after’));
const wait = retryAfter > 0 ? retryAfter * 1000 : 2 ** attempt * 1000 + Math.random() * 1000;
await new Promise((resolve) => setTimeout(resolve, wait));
}
throw new Error(‘Still rate limited after ‘ + attempts + ‘ attempts’);
}
Questo esempio legge Retry-After solo come secondi; il codice di produzione dovrebbe accettare anche il formato data.
Impostare i rate limit sul tuo sito
Rispondi 429, non 503 o 403. Un 503 sembra un downtime e un 403 un rifiuto permanente; un 429 dice a client e strumenti di monitoraggio esattamente cosa è successo.
Invia Retry-After, così i client non devono tirare a indovinare.
Dove puoi, limita per chiave o account. I limiti per IP penalizzano uffici, scuole e reti mobili, dove molte persone condividono un solo indirizzo.
Consenti i picchi. Il caricamento di una pagina può generare decine di richieste insieme; un token bucket con margine per i picchi evita di bloccare i visitatori normali.
Escludi il tuo monitoraggio, oppure dagli un suo endpoint di health check senza limite.
# nginx: 10 requests a second per address, bursts of 20, answered with 429
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429;
}
}
Perché un monitor di uptime può ricevere un 429
Un controllo al minuto sembra innocuo, ma si somma in modi che è facile non notare:
Più monitor sullo stesso host. Dieci monitor sulla stessa API, ognuno con un controllo al minuto, sono dieci richieste al minuto dallo stesso client, più i controlli di conferma quando qualcosa non va.
Limiti severi sul percorso controllato. Pagine di login, ricerche ed endpoint dei moduli spesso consentono solo poche richieste al minuto per indirizzo.
Indirizzi condivisi. I controlli di un servizio di monitoraggio partono da pochi indirizzi noti. Un limite per IP conta insieme tutti i controlli da quell’indirizzo, compresi quelli di altri utenti sullo stesso sito o API pubblica.
Una regola anti-bot che applica rate limit. Alcuni firewall conteggiano a parte i client automatizzati e li limitano più dei browser.
Cosa fare, in quest’ordine: escludi il monitor dal limite tramite i suoi indirizzi IP, monitora un endpoint di health check senza limite, controlla meno spesso oppure accorpa i monitor che colpiscono la stessa API. Non accettare 429 come up in modo generalizzato, perché un limite che inizia a bloccare i tuoi utenti reali è qualcosa che vale la pena sapere. I codici di stato HTTP nel monitoraggio spiega quali codici trattare come errori, e la checklist per il monitoraggio delle API cos’altro tenere d’occhio su un’API.
I 429 e Uptimecheck
Nel monitoraggio uptime e nel monitoraggio delle API di Uptimecheck, un 429 è fuori dagli stati attesi predefiniti (da 200 a 399), quindi risulta down quando un secondo controllo lo conferma. Quando il server risponde con un semplice 429, l’incidente indica che i nostri controlli sono soggetti a rate limit, riporta il valore di Retry-After se il server lo ha inviato e suggerisce di escludere le richieste il cui user agent contiene “Uptimecheck”, di controllare meno spesso o di usare un endpoint senza il limite. I controlli partono da Stoccolma, in Svezia; come consentire Uptimecheck attraverso un firewall elenca gli indirizzi da escludere, con regole per Cloudflare, comprese le sue regole di rate limiting, e per nginx. Scegli tu l’intervallo di ogni monitor, da ogni minuto a ogni ora.
Uptimecheck segue le stesse regole quando invia i tuoi avvisi. Se Slack, Microsoft Teams, Discord o PagerDuty rispondono 429, l’avviso viene ritentato dopo 30 secondi, 2 minuti, 10 minuti e 30 minuti, e mai prima di quanto chiede il Retry-After del servizio, fino a un’ora. Leggi perché gli avvisi potrebbero non arrivare per sapere cosa succede quando un canale continua a fallire.
Distingui un rate limit da un downtime. Prova Uptimecheck gratis per 14 giorni, senza carta di credito.