12 ott 2025·8 min di lettura

Rate limiting per API pubbliche: quote pratiche e flussi di lockout

Limitazione delle richieste per API pubbliche che blocca gli abusi senza penalizzare gli utenti reali: limiti pratici, quote per chiave, lockout e consigli di rollout.

Rate limiting per API pubbliche: quote pratiche e flussi di lockout

Quale problema risolve davvero la limitazione delle richieste

La limitazione delle richieste (rate limiting) per API pubbliche non serve a punire gli utenti. È una valvola di sicurezza che mantiene il servizio disponibile quando il traffico si comporta in modo anomalo, sia che quell"anomalia" sia maliziosa sia che derivi da un bug del client.

"Abuso" spesso sembra normale all'inizio: uno scraper che scorre tutti gli endpoint per copiare dati, tentativi di login brute-force, stuffing di token sulle rotte di autenticazione o un client impazzito che riprova la stessa richiesta in un ciclo stretto dopo un timeout. A volte nessuno ti sta attaccando: un aggiornamento dell'app mobile introduce una cattiva regola di caching e improvvisamente ogni dispositivo interroga la tua API ogni secondo.

Il compito è semplice: proteggere l'uptime e controllare i costi senza bloccare gli utenti reali che svolgono operazioni normali. Se il tuo backend è a consumo (compute, database, email/SMS, chiamate AI), un attore rumoroso può tradursi rapidamente in una spesa reale.

Il rate limiting da solo non basta. Senza monitoraggio e risposte d'errore chiare, ottieni fallimenti silenziosi, clienti confusi e ticket di supporto che suonano come "la vostra API è down" quando in realtà viene limitata.

Una protezione completa di solito include alcuni pezzi distinti:

  • Rate limits: limiti su finestre brevi (per secondo/minuto) che fermano gli spike.
  • Quote: budget su finestre più lunghe (per giorno/mese) che rendono l'uso prevedibile.
  • Lockout: blocchi temporanei per pattern chiaramente abusivi.
  • Eccezioni: allowlist per integrazioni fidate, strumenti interni o clienti VIP.

Se stai costruendo un backend API su una piattaforma come AppMaster, queste regole contano ancora. Anche con codice pulito e rigenerato, vorrai dei default protettivi così un client difettoso non porta giù tutto il servizio.

Termini chiave: rate limits, quote, throttling e lockout

Questi termini si confondono spesso, ma risolvono problemi diversi e si percepiscono diversamente dagli utenti.

Rate limit, quota e concorrenza: cosa significano

Un rate limit è un limite di velocità: quante richieste un client può fare in una finestra breve (al secondo, al minuto). Una quota è un budget: uso totale su un periodo più lungo (giorno, mese). Un limite di concorrenza fissa quante richieste possono essere in corso contemporaneamente, utile per endpoint costosi anche quando il tasso di richieste sembra normale.

Dove applichi il limite conta:

  • Per IP: semplice, ma penalizza reti condivise (uffici, scuole, operatori mobili).
  • Per utente: ottimo per app con login, ma dipende dall'identità affidabile.
  • Per chiave API: comune per API pubbliche, chiaro per ownership e facile da comunicare.
  • Per endpoint: utile quando una rotta è molto più pesante delle altre.

Throttling vs blocco, e dove entra il lockout

Il soft throttling rallenta il client (delay, capacità di burst ridotta) così può riprendersi senza rompere i flussi. Il hard blocking rifiuta le richieste immediatamente, di solito con HTTP 429.

Un lockout è più forte di un normale 429. Un 429 dice "riprovare fra poco." Un lockout dice "fermati fino a quando non si verifica una condizione", come un periodo di cooldown, una revisione manuale o il reset della chiave. Riserva i lockout per segnali chiari di abuso (credential stuffing, scraping aggressivo, auth invalida ripetuta), non per normali spike di traffico.

Se stai costruendo un'API con uno strumento come AppMaster, tratta questi controlli separatamente: limiti su finestre brevi per i burst, quote più lunghe per i costi e lockout solo per comportamenti ripetutamente scorretti.

Scegliere limiti pratici senza indovinare alla cieca

I buoni limiti partono da un obiettivo: proteggere il backend lasciando che gli utenti normali completino il loro lavoro. Non ti servono numeri perfetti il primo giorno. Ti serve una baseline sicura e un modo per aggiustarla.

Un punto di partenza semplice è un limite per chiave API che corrisponda al tipo di API che gestisci:

  • Traffico basso: 60-300 richieste al minuto per chiave
  • Traffico medio: 600-1.500 richieste al minuto per chiave
  • Traffico alto: 3.000-10.000 richieste al minuto per chiave

Poi suddividi i limiti per tipo di endpoint. Le letture sono generalmente più economiche e possono avere limiti più alti. Le scritture modificano i dati, spesso attivano logiche extra, e meritano limiti più restrittivi. Uno schema comune è 1.000/min per le rotte GET e 100-300/min per POST/PUT/DELETE.

Identifica anche gli endpoint costosi e trattali separatamente. Search, generazione di report, esportazioni, upload di file e qualsiasi cosa tocchi più tabelle o esegua logica business pesante dovrebbe avere un bucket più piccolo anche se il resto dell'API è generoso. Se il tuo backend usa workflow visuali (per esempio Business Process flows), ogni step aggiunto è lavoro reale che si moltiplica sotto carico.

Pianifica i burst con due finestre: una finestra corta per assorbire spike rapidi e una più lunga per tenere sotto controllo l'uso sostenuto. Una combinazione comune è 10 secondi più 10 minuti. Aiuta gli utenti reali che cliccano velocemente, senza dare agli scraper una velocità illimitata.

Infine, decidi cosa succede quando il client supera il limite. La maggior parte delle API pubbliche ritorna HTTP 429 con un tempo di retry chiaro. Se il lavoro è sicuro da ritardare (come un export), considera di metterlo in coda invece di bloccarlo rigidamente così gli utenti reali ottengono comunque il risultato.

Progettare quote per chiave che sembrino giuste

Le quote per chiave sono spesso l'approccio più equo perché rispecchiano come i clienti usano il servizio: un account, una chiave API, responsabilità chiare. I limiti basati su IP sono ancora utili, ma spesso penalizzano utenti innocenti.

Gli IP condivisi sono il problema principale. Un intero ufficio può uscire tramite un solo IP pubblico e gli operatori mobili possono raggruppare migliaia di dispositivi in pochi IP. Se ti basi sui limiti per IP, un utente rumoroso può rallentare tutti gli altri. Una quota per chiave evita questo, e puoi mantenere un piccolo limite per IP come backstop per flood evidenti.

Per far sembrare le quote eque, legale ai piani del cliente senza intrappolare i nuovi utenti. Una chiave gratuita o di prova dovrebbe funzionare per test reali, semplicemente non su scala che ti danneggi. Uno schema semplice è burst generosi, rate sostenuto modesto e una quota giornaliera che rispecchia il piano.

Una policy per chiave prevedibile:

  • Permettere burst brevi (caricamenti di pagine, import batch), poi imporre un ritmo costante.
  • Aggiungere un limite giornaliero per chiave per limitare scraping e loop runaway.
  • Aumentare i limiti in base al piano, ma mantenere la stessa struttura per coerenza.
  • Usare un limite più basso per chiavi appena create finché non mostrano una storia positiva.
  • Tenere un piccolo limite per IP per catturare flood ovvi e client mal configurati.

Per scoraggiare condivisione di chiavi e signup automatizzati, non servono sorveglianze pesanti. Parti con controlli semplici come cambi geo insoliti, troppi IP distinti per ora per una singola chiave o molte chiavi nuove create dalla stessa fonte. Segnala e rallenta prima; blocca solo dopo segnali ripetuti.

Il traffico anonimo è dove ha senso essere più severi. Se offri chiavi di prova, limitale strettamente e richiedi un passo di verifica prima di alzare i limiti. Se la tua API alimenta un form pubblico, considera un endpoint anonimo separato con la sua quota così il resto del backend resta protetto.

Se costruisci la tua API con una piattaforma come AppMaster, la logica per chiave è più facile da mantenere coerente perché auth, regole business e gestione delle risposte vivono nello stesso posto.

Risposte e header amichevoli per il client (per far recuperare gli utenti)

Make 429s client-friendly
Create consistent error payloads and headers so clients can back off correctly.
Get Started

Il rate limiting funziona a lungo termine solo se i client capiscono cosa è successo e cosa fare dopo. Punta a risposte prevedibili: stesso codice di stato, stessi campi, stesso significato attraverso gli endpoint.

Quando un client raggiunge un limite, ritorna HTTP 429 (Too Many Requests) con un messaggio chiaro e un tempo di attesa concreto. Il guadagno più veloce è aggiungere Retry-After, perché anche client semplici possono mettere in pausa correttamente.

Un piccolo set di header rende i limiti autoesplicativi. Mantieni nomi coerenti e includili sia nelle risposte di successo (così i client possono autogestirsi) sia nelle 429 (così i client possono recuperare):

  • Retry-After: secondi da attendere prima di ritentare
  • X-RateLimit-Limit: richieste consentite nella finestra corrente
  • X-RateLimit-Remaining: richieste rimaste nella finestra corrente
  • X-RateLimit-Reset: quando la finestra si resetta (epoch seconds o ISO time)
  • X-RateLimit-Policy: testo breve tipo "60 requests per 60s"

Rendi il corpo dell'errore strutturato come le risposte di successo. Un pattern comune è un oggetto error con un code stabile, un message leggibile e suggerimenti di recupero.

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please retry after 12 seconds.",
    "retry_after_seconds": 12,
    "limit": 60,
    "remaining": 0,
    "reset_at": "2026-01-25T12:34:56Z"
  }
}

Dì ai client come fare back off quando vedono 429. L'exponential backoff è un buon default: attendi 1s, poi 2s, poi 4s, e poni un cap (per esempio 30-60 secondi). Sii esplicito anche su quando smettere di ritentare.

Evita sorprese vicino alle quote. Quando una chiave è vicina al cap (per esempio 80-90% usata), includi un campo o un header di avviso così i client possono rallentare prima di iniziare a fallire. Questo conta ancora di più quando uno script può colpire più rotte velocemente e bruciare il budget più in fretta del previsto.

Passo dopo passo: piano di rollout semplice per limiti e quote

Test rate limits safely
Prototype per-key limits and lockout ladders before you ship them to production.
Try It Now

Un rollout funziona meglio quando tratti i limiti come comportamento di prodotto, non come regola una tantum del firewall. L'obiettivo è lo stesso: proteggere il backend mantenendo i clienti normali in movimento.

Inizia con un inventario rapido. Elenca ogni endpoint, poi marca ciascuno per costo (CPU, lavoro DB, chiamate a terze parti) e rischio (login, reset password, search, upload file). Questo ti evita di applicare un unico limite a tutto.

Un ordine di rollout che solitamente evita sorprese:

  • Tagga gli endpoint per costo e rischio, e decidi quali necessitano regole più severe (login, export bulk).
  • Scegli le chiavi d'identità in ordine di priorità: chiave API prima, poi user id, e IP solo come fallback.
  • Aggiungi limiti su finestre brevi (ogni 10 secondi o ogni minuto) per fermare burst e script.
  • Aggiungi quote su finestre più lunghe (per ora o per giorno) per limitare l'uso sostenuto.
  • Aggiungi allowlist per sistemi fidati e strumenti interni così l'operatività non viene bloccata.

Mantieni la prima release conservativa. È più facile allentare dopo che sbloccare utenti arrabbiati.

Monitora e regola, poi versiona la tua policy. Traccia quante richieste incontrano limiti, quali endpoint li attivano e quante chiavi uniche sono coinvolte. Quando cambi i numeri, trattalo come un cambiamento API: documentalo, rilascialo gradualmente e tieni regole vecchie e nuove separate per poter tornare indietro velocemente.

Se costruisci la tua API con AppMaster, pianifica queste regole insieme agli endpoint e alla logica di business così i limiti corrispondono al costo reale di ogni workflow.

Workflow di lockout che fermano l'abuso senza drammi

I lockout sono la cintura di sicurezza. Dovrebbero fermare rapidamente l'abuso evidente, ma dare comunque agli utenti normali una via chiara per recuperare quando qualcosa va storto.

Un approccio calmo è penalità progressive. Presumi che il client sia mal configurato, non necessariamente malizioso, e scala l'azione solo se il pattern si ripete.

Una scala progressiva semplice

Usa pochi step facili da spiegare e da implementare:

  • Avviso: informa il client che sta avvicinandosi ai limiti e quando si resetta.
  • Rallentamento: aggiungi brevi delay o limiti per secondo più stretti per quella chiave.
  • Lockout temporaneo: blocco per minuti (non ore) con un tempo di sblocco preciso.
  • Lockout più lungo: solo dopo burst ripetuti su più finestre.
  • Revisione manuale: per pattern che sembrano intenzionali o persistenti.

Scegliere cosa bloccare è importante. Per chiave API è solitamente più equo perché prende di mira il chiamante, non tutti dietro una rete condivisa. Per account è utile quando gli utenti ruotano le chiavi. Per IP può aiutare con traffico anonimo, ma causa falsi positivi per NAT, uffici e operatori mobili. Quando l'abuso è serio, combina segnali (per esempio blocca la chiave e richiedi controlli extra per quell'IP), ma mantieni il raggio d'azione piccolo.

Rendi i lockout basati sul tempo con regole semplici: "bloccato fino alle 14:05 UTC" e "si resetta dopo 30 minuti di comportamento regolare." Evita ban permanenti per sistemi automatizzati. Un client difettoso può loopare e consumare rapidamente i limiti, quindi progetta penalità che decadono nel tempo. Un periodo sostenuto di basso ritmo dovrebbe ridurre il livello di penalità.

Se stai costruendo la tua API in AppMaster, questa scala si mappa bene su contatori memorizzati più un Business Process che decide allow, slow o block e scrive il tempo di sblocco per la chiave.

Per i recidivi, tieni una via di revisione manuale. Non discutere con gli utenti. Chiedi ID di richiesta, timestamp e il nome della chiave API, poi decidi basandoti sulle evidenze.

Errori comuni che causano falsi positivi

Launch an API you can tune
Stand up a complete backend with APIs, logic, and UI, then iterate your policy over time.
Try Building

I falsi positivi sono quando le tue difese bloccano utenti normali. Di solito succede quando le regole sono troppo semplici per come le persone usano realmente la tua API.

Un errore classico è un unico limite globale per tutto. Se consideri una rotta di lettura economica e un'esportazione costosa allo stesso modo, o iperproteggi la rotta economica (fastidioso) o sottoproteggi quella costosa (pericoloso). Separa i limiti per costo degli endpoint e rendi i percorsi pesanti più restrittivi.

Limitare solo per IP è un'altra trappola comune. Molti utenti reali condividono un IP pubblico (uffici, scuole, operatori mobili, cloud NAT). Un utente pesante può bloccare tutti quanti, e sembra un'outage casuale. Preferisci limiti primari per chiave API, poi usa l'IP come segnale secondario per abusi evidenti.

I guasti possono anche creare falsi positivi. Se il tuo store del limiter è giù, il "fail closed" può portare giù tutta la tua API. Il "fail open" può invitare uno spike che comunque manda giù il backend. Scegli un fallback chiaro: mantieni un piccolo cap d'emergenza al bordo e degrada gradualmente sugli endpoint non critici.

La gestione client conta più di quanto molti team si aspettino. Se ritorni un 429 generico senza un messaggio chiaro, gli utenti ritentano più aggressivamente e scatenano altri blocchi. Invia sempre Retry-After e rendi il testo dell'errore specifico ("Too many requests for this key. Try again in 30 seconds.").

Il problema più evitabile è la segretezza. Limiti nascosti sembrano bug quando i clienti arrivano in produzione per la prima volta. Condividi una policy semplice e mantienila stabile.

Checklist rapida per evitare falsi positivi:

  • Limiti separati per endpoint economici vs costosi
  • Limitazione primaria per chiave API, non solo per IP
  • Comportamento definito quando il limiter non è disponibile
  • Risposte 429 chiare con Retry-After
  • Limiti documentati e comunicati prima dell'applicazione

Se costruisci la tua API con uno strumento come AppMaster, questo spesso significa impostare cap diversi per endpoint e restituire payload d'errore coerenti così i client possono fare back off senza indovinare.

Monitoraggio e alerting che aiutano davvero

Il rate limiting funziona solo se vedi cosa succede in tempo reale. L'obiettivo non è catturare ogni spike, ma individuare pattern che diventano outage o clienti arrabbiati.

Inizia con un piccolo set di segnali che spiegano sia volume che intento:

  • Richieste al minuto (globali e per chiave API)
  • Tasso di 429 (richieste limitate) e tasso di 5xx (dolore del backend)
  • Raffiche di 401/403 (chiavi errate, credential stuffing, client mal configurati)
  • Endpoint top per volume e per costo (query lente, esportazioni pesanti)
  • Endpoint nuovi o inattesi che compaiono nella top 10

Per separare "traffico cattivo" da "abbiamo lanciato qualcosa", aggiungi contesto alle dashboard: tempo di deploy, cambi di feature flag, invii marketing. Se il traffico salta subito dopo un rilascio e il mix 429/5xx resta sano, di solito è crescita, non abuso. Se il salto è concentrato in una chiave, un range IP o un endpoint costoso, trattalo come sospetto.

Gli alert dovrebbero essere noiosi. Usa soglie più cooldown così non vieni svegliato ogni minuto per lo stesso evento:

  • Tasso di 429 sopra X% per 10 minuti, notificare una volta all'ora
  • 5xx sopra Y% per 5 minuti, chiamare subito
  • Singola chiave supera la quota del Z% per 15 minuti, aprire un'indagine
  • Raffiche di 401/403 sopra N/min, segnalare possibile abuso

Quando scatta un alert, tieni una nota d'incidente breve: cosa è cambiato, cosa hai visto (chiavi/endpoint top), e cosa hai aggiustato (limiti, cache, blocchi temporanei). Nel tempo, quelle note diventano il tuo vero playbook.

Esempio: lanci un nuovo endpoint di ricerca e il traffico raddoppia. Se la maggior parte delle chiamate colpisce quell'endpoint su molte chiavi, alza leggermente la quota per chiave e ottimizza l'endpoint. Se una chiave colpisce export senza sosta e aumenta la latenza, limita quell'endpoint separatamente e contatta il proprietario.

Checklist rapida: controlli di buonsenso prima e dopo il lancio

Protect auth and high-risk routes
Add authentication and apply different limits to login, reads, and exports.
Build API

Una buona configurazione è noiosa quando funziona. Questa checklist cattura i problemi che solitamente creano falsi positivi o lasciano buchi evidenti.

Prima di rilasciare un nuovo endpoint

Esegui questi controlli in staging e di nuovo subito dopo il lancio:

  • Identità: conferma che il limiter prenda la chiave giusta (chiave API prima, poi user o IP come fallback), e che le chiavi ruotate non ereditino penalità passate.
  • Limiti: imposta una quota per chiave di default, poi aggiusta in base al costo dell'endpoint (lettura economica vs scrittura costosa) e ai burst previsti.
  • Risposte: ritorna stato e informazioni di recupero chiare (tempo di retry, budget rimanente, codice d'errore stabile).
  • Log: registra chi è stato limitato (key/user/IP), quale rotta, quale regola ha scatenato e un request ID per il supporto.
  • Bypass: tieni una allowlist d'emergenza per i tuoi monitor e integrazioni fidate.

Se costruisci su AppMaster, tratta ogni nuovo endpoint API come una decisione di costo-tier: una semplice lookup può essere generosa, mentre qualsiasi cosa che attiva logica business pesante dovrebbe partire più restrittiva.

Quando succede un incidente (abuso o traffico improvviso)

Proteggi il backend lasciando recuperare gli utenti reali:

  • Alza temporaneamente i cap solo per le rotte meno rischiose (spesso letture) e osserva i tassi di errore.
  • Aggiungi una allowlist temporanea per clienti noti mentre indaghi.
  • Restringi rotte rischiose specifiche invece di abbassare i limiti globali.
  • Attiva identità più forte (richiedi chiavi API, riduci dipendenza dall'IP) per evitare di bloccare reti condivise.
  • Cattura campioni: top keys, top IP, user agent e pattern di payload esatti.

Prima di aumentare i limiti per un cliente, controlla il loro pattern normale di richieste, mix di endpoint e se possono batchare o aggiungere backoff. Conferma anche che non stiano condividendo una chiave tra molte app.

Mensilmente, rivedi: endpoint più limitati, percentuale di traffico che colpisce limiti, nuovi percorsi costosi e se le tue quote corrispondono ancora all'uso reale.

Scenario d'esempio: proteggere una API pubblica reale senza rompere gli utenti

Implement quotas without custom code
Use visual business processes to count requests, apply quotas, and return clear 429 responses.
Create Backend

Immagina di gestire un'API pubblica usata da due app: un portale clienti (alto volume, traffico stabile) e uno strumento admin interno (basso volume, ma azioni potenti). Entrambe usano chiavi API, e il portale ha anche un endpoint di login per gli utenti finali.

Un pomeriggio, un partner rilascia un'integrazione con un bug. Inizia a riprovare richieste fallite in un loop stretto, inviando 200 richieste al secondo da una singola chiave API. Senza guardrail, quella chiave può soffocare tutti gli altri.

I limiti per chiave contengono il raggio d'azione. La chiave difettosa raggiunge il suo cap per minuto, riceve un 429 e il resto dei clienti continua a funzionare. Potresti anche avere un limite separato e più basso per endpoint costosi (come export) così anche il traffico "consentito" non sovraccarica il database.

Contemporaneamente, un tentativo di brute-force sul login inizia a martellare l'endpoint auth. Invece di bloccare tutto il range IP (che potrebbe colpire utenti reali dietro NAT), lo rallenti e poi lo blocchi in base al comportamento: troppe tentativi falliti per account più segnali per IP in una finestra breve. L'attaccante riceve attese progressivamente più lunghe, poi un lockout temporaneo.

Un cliente reale che sbaglia la password qualche volta può comunque recuperare perché le tue risposte sono chiare e prevedibili:

  • 429 con Retry-After così il client sa quando riprovare
  • Un lockout breve (per esempio 10-15 minuti), non un ban permanente
  • Messaggi d'errore coerenti che non rivelano se un account esiste

Per confermare la correzione, osservi alcune metriche:

  • Tasso di 429 per chiave API ed endpoint
  • Tasso di fallimento auth e conteggi di lockout
  • Latency P95 e CPU DB durante l'incidente
  • Numero di chiavi uniche coinvolte (dovrebbe essere piccolo)

Questo è quello che sembra il rate limiting protettivo: protegge il backend senza punire gli utenti normali.

Prossimi passi: mettere in piedi una piccola policy e iterare

Non ti serve un modello perfetto il primo giorno. Parti con una policy piccola e chiara e migliorala mentre impari come si comportano gli utenti reali.

Una prima versione solida di solito contiene tre parti:

  • Una baseline per chiave (richieste al minuto) che copre la maggior parte degli endpoint
  • Cap più stretti per endpoint costosi (search, export, upload file, report complessi)
  • Risposte 429 chiare con un messaggio breve che spiega cosa fare dopo

Aggiungi lockout solo dove il rischio di abuso è alto e l'intento è facile da inferire. Signup, login, reset password e creazione token sono candidati tipici. Mantieni i lockout brevi all'inizio (minuti, non giorni) e preferisci attrito progressivo: rallenta, poi blocca temporaneamente, poi richiedi un controllo più forte.

Scrivi la policy in linguaggio semplice così il supporto può spiegarla senza aiuto ingegneristico. Includi cosa è limitato (per chiave API, per IP, per account), la finestra di reset e come il cliente può recuperare.

Se stai implementando questo mentre costruisci un nuovo backend, AppMaster può essere una soluzione pratica: puoi creare API, definire workflow business (inclusi contatori e decisioni di lockout) in modo visuale, poi distribuire su cloud provider o esportare il codice generato quando vuoi pieno controllo.

Facile da avviare
Creare qualcosa di straordinario

Sperimenta con AppMaster con un piano gratuito.
Quando sarai pronto potrai scegliere l'abbonamento appropriato.

Iniziare