Rate limitDEV
Soglie di rate limiting per categoria di endpoint, header e strategia di retry.
Ogni tenant ha rate limit indipendenti. Il counter è composito: la chiave è tenant + IP del client. Due ristoranti diversi non si tolgono richieste a vicenda; due client dietro lo stesso IP che chiamano lo stesso tenant condividono il limite.
Soglie
| Categoria endpoint | Limite | Limiter |
|---|---|---|
Pubblici read-only (/menu, /categories, /items, /restaurant, /theme, /allergens) |
120 req/min | tenant_public |
Admin (/admin/* scrittura + analytics) |
30 req/min | tenant_admin |
Eventi analytics (POST /analytics/events) |
300 req/min | tenant_analytics |
Header presenti su ogni risposta
HTTP/1.1 200 OK
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Limit— il tetto della finestra (1 minuto)X-RateLimit-Remaining— quante richieste ti restano in questa finestra
Quando saturi il limite
HTTP/1.1 429 Too Many Requests
Retry-After: 47
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
{ "message": "Too Many Attempts." }
Retry-After è in secondi: aspetta almeno quel tempo prima di riprovare.
Strategia di retry consigliata
async function fetchWithRetry(url, opts = {}, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const res = await fetch(url, opts);
if (res.status !== 429) return res;
const retryAfter = Number(res.headers.get('Retry-After')) || (2 ** i);
await new Promise(r => setTimeout(r, retryAfter * 1000));
}
throw new Error('Rate limit superato dopo retry');
}
Stare comodi sotto i limiti
- Cache lato server/edge — i menu cambiano poche volte al giorno: una cache di 5-10 minuti riduce le chiamate del 99% senza degradare l'esperienza utente. Vedi la ricetta WordPress per un esempio pronto con
set_transient. - Paginazione — su
GET /items?per_page=100vai più ampio se devi leggere tutto: meno richieste totali. - Eventi analytics — il limite alto (300/min) è dimensionato per il traffico reale di un menu pubblico; non serve raggrupparli a meno di volumi eccezionali.
Hai bisogno di aiuto?
Scrivi a info@menufacile.it.