Limitation de vitesse Comment éviter de recevoir des erreurs 429 sur chaque API que vous utilisez
HTTP 429 Too Many Requests — comment lire les en-têtes Retry-After, implémenter un retour exponentiel avec jitter, comprendre les algorithmes token bucket vs leaky bucket, et mettre en œuvre un contrôle de vitesse sur votre propre API.
Vous atteignez 429. Votre script a frappé l'API pendant une heure, vos logs sont pleins de messages rouges, et le déploiement est à 20 minutes. C'est le moment où cela cesse d'être abstrait.
L'erreur HTTP 429 « Trop de demandes » signifie que vous avez envoyé plus de demandes que ce que le serveur permet dans une fenêtre de temps donnée. Interpréter correctement la réponse — et réessayer correctement — est une compétence que la plupart des développeurs acquièrent seulement après avoir été blessés. Voici l'ensemble de la situation.
Ce que le 429 vous dit vraiment
Le code d'état n'est qu'une moitié du message. L'information réelle se trouve dans les en-têtes :
Retry-After: 30— attendre 30 secondes avant de réessayer. Peut aussi être une date HTTP :Retry-After: Mon, 08 Jun 2026 15:00:00 GMTX-RateLimit-Limit: 100— nombre total de demandes autorisées dans la fenêtreX-RateLimit-Remaining: 0— nombre de demandes restantes dans la fenêtre actuelle (vous êtes à zéro)X-RateLimit-Reset: 1749391200— timestamp Unix à laquelle la fenêtre se réinitialise
Toutes les APIs ne transmettent pas tous ces éléments. GitHub envoie l'ensemble. Stripe envoie Retry-After. Certains APIs REST envoient rien et attendent que vous deviniez. Si vous avez Retry-After, utilisez-la exactement — c'est le serveur qui vous indique le délai minimum sûr. Si vous ne le faites pas, l'expansion exponentielle est votre fallback.
La mauvaise manière de réessayer
L'implémentation naïve ressemble à cela :
async function fetchWithoutBackoff(url) {
while (true) {
const res = await fetch(url);
if (res.ok) return res;
if (res.status === 429) continue; // immediately retry
}
}
Cela est activement nuisible. Si 10 instances de votre service atteignent simultanément 429 et réessaient immédiatement, chaque réessai arrive au même moment — le problème du troupeau qui frappe. Vous êtes à nouveau limité, immédiatement, dans une boucle serrée qui peut durer indéfiniment et qui fait croire à votre client que vous abusez intentionnellement de l'API.
Retour exponentiel avec bruit
Le modèle correct : chaque réessai attend plus longtemps que le précédent (exponentiel), et un décalage aléatoire empêche les réessais synchronisés sur plusieurs clients (bruit).
async function fetchWithBackoff(url, options = {}, maxRetries = 5) {
let attempt = 0;
while (attempt <= maxRetries) {
const res = await fetch(url, options);
if (res.ok) return res;
if (res.status !== 429) {
throw new Error(`Request failed: ${res.status}`);
}
if (attempt === maxRetries) {
throw new Error(`Rate limited after ${maxRetries} retries`);
}
// Use Retry-After if provided; otherwise exponential backoff + jitter
const retryAfter = res.headers.get('Retry-After');
let waitMs;
if (retryAfter) {
const seconds = isNaN(retryAfter)
? (new Date(retryAfter) - Date.now()) / 1000 // HTTP date
: Number(retryAfter); // seconds
waitMs = seconds * 1000;
} else {
const baseDelay = 1000 * Math.pow(2, attempt); // 1s, 2s, 4s, 8s, 16s
const jitter = Math.random() * 1000; // 0–1000ms random offset
waitMs = baseDelay + jitter;
}
console.log(`Rate limited. Waiting ${Math.round(waitMs / 1000)}s (attempt ${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, waitMs));
attempt++;
}
}
La ligne du bruit est la partie la plus souvent oubliée. Sans elle, les réessais provenant de plusieurs processus parallèles arrivent encore en groupes. Avec elle, ils se répartissent dans la fenêtre d'attente.
Pour les APIs qui retournent Retry-After, utilisez cette valeur comme la plafond — si vous continuez à recevoir des 429 après l'attente spécifiée, appliquez un retour exponentiel en plus.
Bouteille de jetons vs bouteille de fuite
Deux algorithmes dominent les implémentations de limitateurs de vitesse. Comprendre lequel vous êtes en train de traiter vous apprend beaucoup sur la manière dont l'API se comporte sous pression — et quel algorithme choisir lorsque vous construisez votre propre solution.
Bouteille de jetons
La bouteille contient jusqu'à N jetons. Chaque demande coûte 1 jeton. Les jetons se remplissent à un rythme fixe (par exemple, 10 par seconde). Si la bouteille est vide, la demande est rejetée ou mise en file d'attente.
Adaptée aux pics. Si vous n'avez pas fait de demandes depuis un certain temps, vous avez accumulé des jetons et pouvez envoyer un pic sans dépasser la limite. L'API GitHub fonctionne ainsi — 5 000 demandes par heure, mais vous pouvez les utiliser en une seule fois si vous n'avez pas utilisé l'API depuis des heures. Idéal pour les cas interactifs où le trafic est irrégulier.
Bouteille de fuite
Les demandes entrent dans une file d'attente et s'écoulent à un rythme fixe, quel que soit le rythme de leur arrivée. Si la file d'attente est pleine, les demandes entrantes sont rejetées.
Sortie lisse, sans pics. Même si vous avez encore de la quota, les demandes sortent progressivement au rythme configuré. Le module limit_req de Nginx utilise cela. Idéal pour protéger les systèmes en aval des pics — utile pour la livraison de webhooks, les appels à des APIs externes, et tout ce qui nécessite un débit prédicteur plutôt que de tolérer des pics.
Quel choisir lorsque vous implémentez votre propre solution : Des points d'accès destinés aux utilisateurs nécessitant une tolérance aux pics → bouteille de jetons. Livraison de webhooks ou appels à des APIs externes → bouteille de fuite. Tâches en arrière-plan où un débit régulier est important → bouteille de fuite.
Calculer les taux de demandes sûrs
Avant d'écrire toute logique de réessai, déterminez ce que vous êtes vraiment autorisé à faire. Si une API dit « 1 000 demandes par heure », cela fait 16,67 demandes par minute ou 0,278 demande par seconde. Ajoutez un buffer de sécurité de 20% et vous êtes à environ 13 demandes par minute — assez d'espace pour éviter les problèmes de timing aux limites où deux fenêtres se superposent.
Utilisez le Calculateur de vitesse limite pour convertir les nombres de quota en taux par seconde ou par minute, trouver l'intervalle de pause entre les demandes, et voir comment votre niveau de concurrence affecte le risque de pics.
Implémentation de la limitation de vitesse sur votre propre API
Si vous êtes de l'autre côté et souhaitez ajouter un comportement correct de 429 à votre propre API :
- Choisissez la bonne granularité. Par adresse IP est facile mais ne fonctionne pas pour les services derrière un NAT ou partageant une sortie. Par clé d'API est meilleur mais nécessite une authentification. Par ID utilisateur est idéal si vous en avez. Ne mélangez pas les granularités sans savoir quel est le gagnant.
- Retournez toujours
Retry-After. Un 429 sansRetry-Afterforce chaque client à implémenter son propre algorithme de réessai. Vous obtiendrez davantage de troupeaux qui frappent, pas moins. - Utilisez Redis pour la limitation de vitesse distribuée. Les compteurs en mémoire ne fonctionnent pas entre plusieurs instances de serveur. Redis
INCR+EXPIREest le modèle standard. Les bibliothèques comme rate-limiter-flexible (Node) et slowapi (Python/FastAPI) le gèrent correctement. - Enregistrez chaque 429 que vous émettez. Une augmentation des 429 provenant d'une seule clé est soit une erreur client, soit une utilisation intentionnelle abusive. Les deux cas méritent d'être connus en temps réel.
- Ne limitez pas la vitesse sur une erreur d'authentification. Retournez 401 pour des identifiants incorrects, pas 429. Limiter la vitesse sur une mauvaise authentification est la manière dont vous verriez accidentellement bloquer vos propres utilisateurs lors d'une rotation des identifiants.
Ce que vous devez faire immédiatement
Si vous recevez des 429 :
- Vérifiez
Retry-Afterd'abord — utilisez-le s'il est disponible, ne créez pas votre propre délai - Implémentez un retour exponentiel avec bruit — le code ci-dessus est prêt à copier-coller
- Enregistrez la
X-RateLimit-Remainingen-tête sur chaque réponse — vous pourriez consommer votre quota plus vite que vous ne le pensez - Cachez les réponses lorsque les données ne changent pas fréquemment
Si vous implémentez une limitation de vitesse : choisissez une bibliothèque basée sur Redis, retournez Retry-After à chaque 429, surveillez le taux de 429 par clé, et ne limitez pas la vitesse sur une erreur d'authentification.
Le 429 n'est pas l'ennemi — c'est l'API qui vous indique exactement ce qui s'est produit et (généralement) combien de temps attendre. La plupart des problèmes de limitation de vitesse viennent de l'ignorer ce message et de réessayer immédiatement. Ne faites pas cela.
Installez nos extensions
Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide
恵 Le Tableau de Bord Est Arrivé !
Tableau de Bord est une façon amusante de suivre vos jeux, toutes les données sont stockées dans votre navigateur. D'autres fonctionnalités arrivent bientôt !
Outils essentiels
Tout voir Nouveautés
Tout voirMise à jour: Notre dernier outil a été ajouté le 7 juin 2026
