HTTP 429 : gérer Retry-After et les relances sans créer de doublons

Une réponse HTTP 429 demande de réduire la pression sur une API, pas de relancer immédiatement toute l’automatisation. Pour la traiter proprement, il faut lire les indications du service, vérifier que l’opération peut être répétée, espacer les essais et prévoir un arrêt.

Ce guide concerne la conception d’un client API ou d’un workflow. La politique chiffrée proposée plus bas est un exemple à adapter au contrat de l’API, pas un réglage universel ni le comportement garanti d’un SDK.

1. Lire la réponse avant de choisir une stratégie

La RFC 6585 définit 429 Too Many Requests comme une limitation du nombre de requêtes sur une période. Elle ne fixe ni une limite identique pour tous les services, ni une méthode unique de comptage. Un même identifiant peut, par exemple, partager une limite entre plusieurs traitements.

Relevez le code d’erreur applicatif, les informations de quota documentées et l’éventuel en-tête Retry-After. Cet en-tête est facultatif : son absence n’autorise pas une boucle rapide. Vérifiez dans la documentation si la situation est temporaire ou demande une action sur le compte ou la configuration.

Évitez de changer de clé ou d’identité pour contourner la limite. Cherchez plutôt quels traitements consomment le même budget d’appels et réduisez leur concurrence si nécessaire.

2. Interpréter Retry-After sans raccourcir l’attente

Retry-After accepte deux formes : un délai entier en secondes après réception ou une date HTTP. Exemple fictif :

HTTP/1.1 429 Too Many Requests
Retry-After: 60

Ici, prévoyez au moins 60 secondes avant une nouvelle tentative, si elle est autorisée. Avec une date HTTP, calculez le délai restant jusqu’à cette date avec une horloge correcte. Une valeur illisible doit être traitée explicitement ; ne la convertissez pas silencieusement en zéro.

Si le serveur demande une attente supérieure au temps disponible pour votre traitement, arrêtez ou différez l’opération. Ne ramenez pas arbitrairement son délai à votre plafond local pour continuer plus vite.

3. Ne pas rejouer une écriture sans garantie

Un délai d’attente réseau dépassé ne prouve pas que le serveur n’a rien fait. C’est important pour une création de commande ou l’envoi d’un message : relancer tout le workflow peut répéter des actions déjà réussies.

La RFC 9110 déconseille la relance automatique d’une méthode non idempotente sans moyen de savoir que l’opération est répétable ou qu’elle n’a pas été appliquée. Idempotent signifie ici que répéter la même demande conserve le même effet voulu, pas nécessairement la même réponse.

Quand une API propose une clé d’idempotence, suivez son contrat. Stripe documente, par exemple, la réutilisation d’une clé pour reconnaître les essais d’une même demande. Conservez la clé et les paramètres de cette opération entre ses tentatives ; une nouvelle clé à chaque essai ne remplit pas ce rôle. Vérifiez aussi la durée de conservation prévue par le service.

4. Combiner attente progressive, hasard et limites

Le backoff augmente l’attente entre les échecs ; le jitter ajoute une part aléatoire pour éviter que plusieurs clients repartent ensemble. Google décrit ce principe pour IAM, avec un plafond et une échéance. Les erreurs auxquelles l’appliquer restent propres à chaque API.

Voici une proposition pédagogique pour une opération déjà jugée sûre à rejouer : six tentatives au maximum, appel initial compris ; un budget global de 90 secondes ; au plus 10 secondes pour chaque appel. Avant chaque relance, avec n = 0 pour la première :

base = min(16 secondes, 1 seconde × 2^n)
R = délai serveur valide restant, sinon 0 si aucun délai exploitable
attente = max(R, base) + aléa entre 0 et 1 seconde

Le plafond de 16 secondes concerne la base locale, pas l’indication du serveur ni l’attente totale. Avec Retry-After: 60, la première attente sera donc comprise entre 60 et 61 secondes, pas ramenée à 16. Sans délai exploitable, le repli local n’est acceptable que si la documentation permet de retenter.

Avant d’attendre puis avant d’envoyer, contrôlez le budget restant. Chaque appel doit avoir une limite effective qui ne dépasse pas ce reste. Si le budget ou le nombre d’essais est épuisé, retournez un échec explicite. Après un résultat réseau ambigu sur une écriture, réévaluez sa sécurité au lieu de poursuivre mécaniquement.

5. Éviter les relances à plusieurs étages

Inspectez les réglages du SDK avant d’ajouter une boucle autour de lui. Certains clients gèrent déjà les relances : la documentation AWS en décrit les limites et la classification des erreurs, avec des différences selon les versions et les modes.

Si votre boucle autorise trois appels au SDK et que chacun produit trois tentatives HTTP, vous pouvez obtenir neuf requêtes, pas trois. AWS recommande généralement un point de relance dans la pile pour les opérations peu coûteuses. Identifiez clairement cette couche et comptez les appels effectivement envoyés.

6. Tester avec un faux serveur, puis suivre les résultats

Avant un déploiement, simulez les réponses sans consommer de quota réel. Votre jeu de tests devrait notamment vérifier :

  • 429 avec Retry-After, puis succès : aucune relance avant le délai retenu.
  • 429 sans en-tête ou avec une valeur invalide : repli documenté ou arrêt explicite, jamais boucle sans pause.
  • Délai serveur supérieur au budget : aucun nouvel appel immédiat.
  • Échecs répétés : arrêt au nombre d’essais ou à l’échéance, même si le serveur continue de répondre.
  • Écriture avec résultat incertain : pas de nouvelle création aveugle ; contrôle de l’état ou mécanisme d’idempotence prévu.

Conservez un identifiant de traitement, le nombre de tentatives réelles, les statuts reçus et les attentes appliquées. Ne journalisez pas les jetons d’accès ni les corps contenant des données personnelles. Ces traces doivent permettre de comprendre un arrêt et de reprendre le travail sans refaire les étapes déjà validées.

À retenir

Une bonne gestion de HTTP 429 ne consiste pas seulement à ajouter une pause. Elle combine le contrat du fournisseur, la répétabilité de l’opération, un délai serveur respecté et des relances bornées. Si les limites restent atteintes, revoyez le débit et l’organisation des appels plutôt que d’allonger indéfiniment la boucle.

Sources

Publications similaires