Hai un'API pubblica? Se non hai implementato il rate limiting, qualcuno la sta probabilmente usando per fare scraping, DDoS o brute force. Non è una questione di 'se', ma di 'quando'. Noi, di Meteora Web, lo vediamo ogni giorno nei progetti che ci arrivano: API senza protezione che collassano sotto un carico malevolo o che bruciano budget di terze parti perché un client mal configurato invia richieste senza controllo.
In questa guida operativa ti mostriamo cos'è il rate limiting, come implementarlo in Node.js, Express e NGINX, e quali strategie di throttling utilizzare per proteggere le tue API senza penalizzare gli utenti legittimi.
Cosa sono rate limiting e throttling e perché sono fondamentali per le API?
Rate limiting è il controllo del numero di richieste che un client può fare in un determinato intervallo di tempo. Ad esempio: massimo 100 richieste ogni 15 minuti per IP. Throttling è una variante più morbida: invece di bloccare, si rallenta la risposta o si riduce la priorità. Spiegato con un'analogia: il rate limiting è un semaforo che diventa rosso (blocco), il throttling è un dosso stradale che costringe a rallentare.
Perché servono? Protezione da abusi, sicurezza, equità, costi. Un cliente e-commerce che avevamo seguito aveva un'API di catalogo pubblica senza limiti. Un concorrente ha fatto scraping di tutto il database ogni 10 secondi per giorni. Con un semplice rate limiting avremmo fermato tutto. Invece il server è andato in tilt e il cliente ha perso vendite per ore.
Sponsored Protocol
Un'API senza rate limiting è come una banca senza porte: prima o poi qualcuno entra. Se gestisci un servizio che integra API di terze parti a pagamento (es. OpenAI, Stripe), il rate limiting ti evita di superare il budget per un loop infinito.
Azione per te: Verifica subito se la tua API ha un limite. Apri un terminale e lancia 50 richieste consecutive con curl. Se ottieni sempre 200, sei vulnerabile.
Come implementare il rate limiting in un'API REST con Node.js e Express?
Il modo più rapido e robusto per aggiungere rate limiting a un'API Express è il middleware express-rate-limit. Supporta finestre fisse, sliding window con Redis e header standard. Noi lo usiamo in produzione per decine di progetti.
Installa il pacchetto:
npm install express-rate-limitConfigurazione base:
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minuti
max: 100, // limite di 100 richieste per finestra
standardHeaders: true,
legacyHeaders: false,
message: { error: 'Troppe richieste. Riprova tra qualche minuto.' }
});
// Applica a tutte le route /api/
app.use('/api/', limiter);Puoi personalizzare per route diverse. Ad esempio, per l'autenticazione (soggetta a brute force) usa limiti più stretti:
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: { error: 'Troppi tentativi di login. Riprova tra 15 minuti.' }
});
app.use('/api/auth/login', authLimiter);Attenzione: In ambiente multi-server usa un store condiviso come Redis. Ecco un esempio con rate-limit-redis:
Sponsored Protocol
const RedisStore = require('rate-limit-redis');
const redisClient = require('./redis');
const limiter = rateLimit({
store: new RedisStore({
sendCommand: (...args) => redisClient.call(...args),
}),
windowMs: 15 * 60 * 1000,
max: 100,
});Azione per te: Aggiungi questo middleware al tuo progetto. Testa con un semplice script:
for i in {1..110}; do curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/api/ | tail -n 5Dovresti vedere 429 dopo il centesimo tentativo.
Quali strategie di throttling scegliere per il tuo caso d'uso?
Non tutte le API hanno lo stesso pattern di traffico. Ecco le strategie più comuni, con pro e contro:
- Fixed Window (finestra fissa): conta le richieste in un intervallo di tempo fisso. Semplice, ma permette burst al confine della finestra. Buona per iniziare.
- Sliding Window (finestra scorrevole): tiene traccia dei timestamp delle richieste, più preciso. Noi la usiamo quasi sempre in produzione con Redis.
- Token Bucket: accumula token nel tempo, permette picchi controllati. Ideale per API con burst occasionali (es. notifiche push).
- Leaky Bucket: le richieste entrano in una coda e vengono elaborate a velocità costante. Utile per backend con risorse limitate.
Noi, di Meteora Web, abbiamo scelto lo sliding window con Redis per un cliente che integrava l'API di un servizio di fatturazione con piani a consumo. Con un semplice token bucket sforavamo il budget durante i picchi. Con lo sliding window abbiamo limitato le richieste in modo granuale, risparmiando centinaia di euro al mese.
Sponsored Protocol
Come implementare sliding window con Redis manualmente? Puoi usare lo store Redis di express-rate-limit (mostrato sopra) oppure scrivere una logica custom con ZADD e ZREMRANGEBYSCORE. Ecco un esempio semplificato:
const WINDOW = 60; // secondi
const MAX = 10;
async function rateLimit(clientId) {
const now = Date.now();
const key = `ratelimit:${clientId}`;
const multi = redisClient.multi();
multi.zremrangebyscore(key, 0, now - WINDOW * 1000);
multi.zadd(key, now, now);
multi.zcard(key);
multi.expire(key, WINDOW);
const results = await multi.exec();
const count = results[2][1];
if (count > MAX) {
throw new Error('Rate limit exceeded');
}
}Azione per te: Se hai già un'API in produzione, passa dallo store in memoria a Redis con sliding window. I client che usano fixed window spesso segnalano burst inaspettati. Testa la nuova configurazione simulando carico con Artillery.
Come proteggere le API con NGINX o API Gateway?
Non sempre vuoi modificare il codice dell'applicazione. A livello di reverse proxy o API Gateway puoi implementare il rate limiting in modo trasparente. NGINX, che molti già usano, offre il modulo limit_req. Configurazione esempio:
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://backend;
}
}
}Qui permettiamo 10 richieste al secondo per IP, con un burst massimo di 20. Le richieste in eccesso ricevono 503 (di default). Vantaggi: nessuna modifica al backend, configurazione centralizzata. Svantaggio: meno flessibilità rispetto a una logica applicativa (es. limiti diversi per utente autenticato vs anonimo).
Sponsored Protocol
Un'alternativa più strutturata sono API Gateway come Kong o AWS API Gateway. Per progetti complessi sono utili, ma attenzione al vendor lock-in. Noi preferiamo soluzioni che lasciano il controllo al cliente – un NGINX ben configurato con Lua scripting può fare tutto quello che fa un gateway enterprise.
Azione per te: Se hai già un proxy NGINX, aggiungi la direttiva limit_req al blocco della tua API. Poi testa con wrk o siege. Esempio con wrk:
wrk -t2 -c20 -d10s http://localhost/api/Osserva quanti 503 ricevi. Regola i parametri fino a trovare il punto di equilibrio.
Come monitorare e testare il rate limiting in produzione?
Il rate limiting non va mai lasciato senza sorveglianza. Tre cose da fare subito:
- Aggiungi header di risposta. Express-rate-limit li aggiunge automaticamente se
standardHeaders: true. RiceveraiX-RateLimit-Limit,X-RateLimit-RemainingeRetry-Aftersui 429. Anche NGINX può esporli conlimit_req_statuse log. - Logga ogni blocco. Esempio con Express: usa un handler personalizzato.
- Imposta alert. Se il numero di 429 supera una soglia, qualcosa sta andando storto (un attacco o un falso positivo).
Testa il sistema con uno script di carico. Ecco un comando semplice per vedere il comportamento in locale:
Sponsored Protocol
for i in {1..120}; do curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" http://localhost:3000/api/; done | sort | uniq -cDovresti vedere una miscela di 200 e 429. Se ottieni solo 200, il rate limiting non funziona.
Azione per te: Imposta un alert su Grafana o via webhook quando la percentuale di 429 supera il 5% del totale delle richieste al minuto. Se hai un'API esterna, usa il file di log per analizzare gli IP bloccati.
Cosa fare adesso
Ecco la checklist operativa per mettere in sicurezza la tua API:
- Identifica le route critiche (login, registrazione, ricerca, checkout).
- Scegli la strategia – fissa per semplicità, sliding window per produzione.
- Implementa con express-rate-limit (Node.js) o limit_req (NGINX).
- Configura header e logging per il debug e il monitoraggio.
- Testa con strumenti di carico (wrk, artillery, autocannon).
- Monitora in produzione – alert su troppi 429.
Se non hai tempo o competenze per implementarlo, contattaci. Noi di Meteora Web lo facciamo per i nostri clienti ogni settimana, integrandolo in architetture fatte su misura. Il rate limiting non è un lusso: è una porta blindata per la tua API. Non aspettare che qualcuno la sfondi.