# Idempotence et limitation de débit : clés, 429, Retry-After, RateLimit

> L'en-tête Idempotency-Key (draft IETF) rend un POST rejoué sûr : le serveur stocke le premier résultat par clé dans une fenêtre de déduplication et le rejoue pour tout doublon, offrant une soumission exactly-once. La limitation de débit protège le service : les requêtes hors limite reçoivent 429 Too Many Requests avec Retry-After, et les en-têtes RateLimit annoncent le quota restant pour que les clients s'auto-régulent.

- URL canonique: https://www.broadnet.me/fr/reference/idempotency-and-rate-limiting
- Langue: fr
- Dernière mise à jour: 2026-07-19
- Éditeur: BroadNet (https://www.broadnet.me)

Deux motifs HTTP en voie de standardisation pour des clients sûrs et bien élevés : l'en-tête Idempotency-Key (draft IETF) pour une soumission exactly-once avec fenêtre de déduplication et rejeu de réponse, et la limitation de débit — 429 avec Retry-After, les en-têtes RateLimit / RateLimit-Policy (draft IETF), les token buckets et la contre-pression côté client.

## L'en-tête Idempotency-Key

La soumission de message est un POST, qui n'est pas idempotent, et pourtant les réseaux forcent les clients à rejouer quand une réponse est perdue — créant le classique double envoi. Le draft Idempotency-Key du groupe de travail HTTP-API de l'IETF standardise le remède : le client génère une clé unique (un UUID) par opération logique et l'envoie dans l'en-tête de requête Idempotency-Key. Le serveur enregistre la clé avec le résultat de la première requête, et s'il revoit la même clé il n'exécute pas une seconde fois — il renvoie le résultat stocké. Ainsi une reprise après un timeout est garantie inoffensive : soit la première tentative n'a jamais abouti (et celle-ci s'exécute), soit elle l'a fait (et son résultat est rejoué). La clé appartient à l'opération, non à la connexion, si bien que le client réutilise la même clé à chaque reprise de cet unique envoi.

*POST idempotent avec une clé générée par le client*

```http
# Generic IETF-draft example (not the BroadNet API, which takes no
# Idempotency-Key header: see /developers/idempotency)
POST /v1/messages HTTP/1.1
Host: api.example
Idempotency-Key: 8f14e45f-ea7b-4c0f-9b2a-1d2c3e4f5a6b
Content-Type: application/json

{ "to": "+15551234567", "text": "..." }

# first call  -> 202 Accepted, id 01HZY8Q3M6   (executed, stored)
# same key    -> 202 Accepted, id 01HZY8Q3M6   (replayed, not re-sent)
```

## Fenêtre de déduplication, rejeu de réponse et conflits

Une clé d'idempotence n'est pas mémorisée à jamais ; le serveur la conserve pendant une fenêtre de déduplication (couramment 24 heures) assez longue pour couvrir toute reprise réaliste, puis l'expire. Dans cette fenêtre, un doublon de la clé rejoue le code de statut et le corps stockés verbatim — le même 202 et le même id de message — pour que le client voie exactement ce qu'il aurait vu si la première réponse était arrivée. Deux cas limites requièrent un traitement explicite. Si une clé est réutilisée avec un corps de requête différent, c'est un bug client et le serveur renvoie 409 Conflict plutôt que d'envoyer silencieusement la mauvaise chose. Si une reprise arrive pendant que la première requête est encore en vol, le serveur renvoie un conflit ou un « in progress » plutôt que de démarrer une seconde exécution, pour que la concurrence ne puisse défaire la garantie.

*Résultats d'Idempotency-Key*

| Situation | Comportement du serveur | Statut |
|---|---|---|
| Nouvelle clé | Exécuter, stocker la clé + le résultat | Normal (ex. 202) |
| Clé répétée, même corps | Rejouer la réponse enregistrée, ne pas réexécuter | Statut d'origine |
| Clé répétée, corps différent | Rejeter — clé liée à la première charge utile | 409 Conflict |
| Répétition pendant que la première est encore en cours | Ne lancez pas une seconde exécution | 409 / en cours |
| Clé expirée (hors fenêtre) | Traité comme nouveau | Normal |

## Limitation de débit et 429

Une plateforme de messagerie partagée se protège elle-même et les autres locataires en plafonnant la vitesse à laquelle un client peut appeler, et signale un dépassement avec un statut précis. RFC 9110 et RFC 6585 définissent 429 Too Many Requests exactement pour cela : le client a envoyé trop de requêtes dans un intervalle donné. Un serveur bien élevé associe le 429 à un en-tête Retry-After indiquant au client combien de temps attendre avant de réessayer (soit un délai en secondes, soit une date HTTP). L'obligation du client est de l'honorer — s'arrêter, attendre l'intervalle indiqué, puis reprendre — plutôt que de réessayer immédiatement, ce qui ne fait qu'aggraver la surcharge. Un 429 est transitoire et rejouable sans risque, contrairement à un 4xx qui indique une requête mal formée.

*429 avec les en-têtes Retry-After et RateLimit*

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 2
RateLimit: limit=100, remaining=0, reset=2
RateLimit-Policy: 100;w=1
Content-Type: application/problem+json

{ "type": "https://example/problems/rate-limited",
  "title": "Too Many Requests", "status": 429 }
```

## Les en-têtes RateLimit et RateLimit-Policy

Réagir à un 429 après coup est du gaspillage ; le draft RateLimit-headers de l'IETF laisse un client voir son budget avant de le dépasser. Sur les réponses ordinaires, le serveur annonce le quota courant avec un en-tête RateLimit portant la limite, l'allocation restante et les secondes jusqu'à la réinitialisation de la fenêtre, et un en-tête RateLimit-Policy décrivant la politique elle-même (par exemple 100 requêtes par fenêtre d'une seconde). Un client qui les lit peut se réguler — ralentissant à mesure que remaining approche de zéro — et ne jamais déclencher de 429. Cela transforme la limitation de débit d'un rejet punitif après coup en un signal coopératif, ce qui est tout l'intérêt de standardiser les noms d'en-têtes pour que toute bibliothèque cliente puisse les consommer.

*En-têtes standard de signalisation de limitation de débit*

| En-tête | Transporte | Exemple |
|---|---|---|
| 429 Too Many Requests | L'état de dépassement de limite | ligne d'état |
| Retry-After | Combien de temps attendre avant de réessayer | Retry-After: 2 |
| RateLimit | limit / remaining / reset pour la fenêtre | limit=100, remaining=17, reset=1 |
| RateLimit-Policy | La politique de quotas en vigueur | 100;w=1 (100 per 1s) |

## Token bucket et application des limites

L'algorithme token bucket est le mécanisme habituel derrière ces en-têtes car il plafonne le débit soutenu tout en tolérant de courtes rafales. Un seau contient jusqu'à un nombre fixe de jetons et se recharge à un débit régulier ; chaque requête retire un jeton, et une requête qui trouve le seau vide est rejetée avec un 429. La taille du seau fixe la rafale qu'un client peut dépenser d'un coup et le débit de recharge fixe le plafond à long terme, si bien qu'un client peut envoyer une rafale rapide après une période d'inactivité mais ne peut dépasser la moyenne. La valeur remaining de RateLimit est en fait le compte de jetons, et reset est le moment où le seau sera rechargé — ce qui est exactement l'information dont un client régulé a besoin. Ce contrôle de flux à la couche HTTP est l'analogue REST du dimensionnement de fenêtre SMPP et du throttling enquire_link sur la session binaire.

## Contre-pression côté client

La moitié cliente d'un bon comportement face à la limitation de débit est la contre-pression : modeler la charge sortante pour qu'elle reste dans le budget annoncé au lieu de tout tirer et d'absorber des 429. En pratique, cela signifie un limiteur côté client (un token bucket reflétant celui du serveur), la lecture des en-têtes RateLimit pour ajuster le rythme, et sur un 429 un backoff pendant l'intervalle Retry-After avec jitter avant de reprendre. Pour un envoi en masse, cela signifie doser les soumissions au plafond soutenu plutôt que de les déverser, pour que la plateforme reste saine et que la latence du client reste prévisible. BroadNet documente son comportement concret d'idempotence et de limitation de débit pour les développeurs.

## Questions fréquentes

### À quoi sert l'en-tête Idempotency-Key ?

Il rend un POST rejoué sûr. Le client envoie une clé unique par opération logique ; le serveur exécute la première requête avec cette clé et stocke le résultat, puis rejoue le résultat stocké pour tout doublon de la même clé dans une fenêtre de déduplication. Ainsi une reprise après une réponse perdue s'exécute une seule fois ou se rejoue — jamais de double envoi. C'est spécifié dans un draft du groupe de travail HTTP-API de l'IETF.

### Combien de temps le serveur mémorise-t-il une clé d'idempotence ?

Pendant une fenêtre de déduplication — couramment autour de 24 heures — assez longue pour couvrir toute reprise réaliste, après quoi la clé expire et une réutilisation est traitée comme nouvelle. Dans la fenêtre, un doublon de la clé rejoue le code de statut et le corps d'origine verbatim plutôt que de réexécuter.

### Que se passe-t-il si je réutilise une clé d'idempotence avec un corps différent ?

Le serveur la rejette avec 409 Conflict. La clé est liée à la charge utile de la première requête, si bien que la réutiliser avec un corps différent est traité comme une erreur client plutôt que d'envoyer silencieusement le mauvais message. Ne réutilisez la même clé que pour les reprises de l'opération identique.

### Que doit faire un client lorsqu'il reçoit un 429 ?

S'arrêter et honorer l'en-tête Retry-After — attendre les secondes indiquées (ou jusqu'à la date donnée), puis reprendre — plutôt que de réessayer immédiatement, ce qui ne fait qu'aggraver la surcharge. Un 429 est transitoire et rejouable sans risque une fois l'attente écoulée, idéalement avec un peu de jitter pour que de nombreux clients ne reprennent pas à l'unisson.

### À quoi servent les en-têtes RateLimit et RateLimit-Policy ?

Ils laissent un client voir son quota avant de le dépasser. RateLimit porte la limite, l'allocation restante et l'heure de réinitialisation de la fenêtre courante ; RateLimit-Policy décrit la politique (par exemple 100 requêtes par seconde). Un client qui les lit peut se réguler et éviter tout 429. Les deux sont définis dans un draft IETF.

### Quel est le lien entre un token bucket et les en-têtes RateLimit ?

Le token bucket est le mécanisme d'application : un seau de taille fixe se recharge à un débit régulier, chaque requête dépense un jeton, et un seau vide donne un 429. La valeur remaining de RateLimit est essentiellement le compte de jetons courant et reset est le moment où le seau se recharge — si bien qu'un client lisant ces en-têtes sait exactement combien de rafale et de débit soutenu il lui reste.

## Sources

- [IETF draft — Idempotency-Key HTTP Header Field](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-idempotency-key-header)
- [IETF draft — RateLimit header fields for HTTP](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-ratelimit-headers)

## Voir aussi

- [Conception d'API de messagerie REST](https://www.broadnet.me/fr/reference/rest-messaging-api-design)
- [Livraison et fiabilité des webhooks](https://www.broadnet.me/fr/reference/webhook-delivery-and-reliability)
- [SMPP enquire_link et throttling](https://www.broadnet.me/fr/reference/smpp-enquire-link-throttling)
- [Guide d'idempotence BroadNet](https://www.broadnet.me/developers/idempotency)
- [Limites de débit BroadNet](https://www.broadnet.me/fr/developers/rate-limits)
