Une requête peut parvenir au serveur sans que le client reçoive la réponse. Le délai d’attente a peut-être expiré après l’enregistrement d’un paiement ou la création d’une commande. Si le client réessaie sans précaution, le système risque de répéter l’opération. L’idempotence des API aide à éviter ce résultat : elle permet de reconnaître plusieurs requêtes comme relevant d’une même tentative métier et d’en limiter les effets en double.
Mais ajouter un en-tête contenant une clé ne suffit pas. Il faut décider qui la génère, combien de temps elle reste valide, quelle réponse renvoyer de nouveau et comment coordonner les écritures locales avec les services externes. L’objectif n’est ni de masquer les erreurs ni de promettre une exécution exactement une fois : il s’agit de rendre les nouvelles tentatives sûres dans des conditions explicites.
Ce que signifie l’idempotence et le problème qu’elle résout

Une opération est idempotente lorsque sa répétition avec les mêmes données ne modifie pas le résultat final après la première exécution. Par exemple, définir l’adresse de livraison d’une commande à une valeur précise peut être idempotent : appliquer deux fois la même mise à jour laisse la ressource dans le même état qu’une seule application.
À l’inverse, une opération telle que « ajouter une unité au panier » n’est pas idempotente par elle-même : la répéter peut augmenter la quantité deux fois. La création d’une commande ou l’enregistrement d’un débit peut également produire des effets supplémentaires si chaque requête est considérée comme une nouvelle intention. Pour ce type d’opérations, une clé d’idempotence peut associer les nouvelles tentatives à la même tentative logique.
L’idempotence ne signifie pas que toutes les réponses sont identiques ni que la requête ne peut jamais échouer. Elle consiste à contrôler les effets de sa répétition conformément à un contrat. Un client peut recevoir une erreur puis, en réessayant, obtenir le résultat déjà enregistré ; il peut aussi recevoir de nouveau une erreur définitive. L’essentiel est que le serveur ne produise pas par inadvertance un second effet.
Quand ajouter l’idempotence et quand s’en passer
Le risque apparaît lorsqu’une opération produit des effets importants et que le client ne peut pas savoir avec certitude si le serveur l’a menée à bien. Une réponse perdue, un délai d’attente dépassé, une déconnexion ou une nouvelle tentative automatique peuvent rendre le résultat incertain. Cette situation est particulièrement sensible lors de la création de commandes, du lancement de paiements, de la réservation de stocks ou du traitement de demandes.
Avant d’ajouter des clés, examinez le contrat existant. Une mise à jour qui définit un état précis peut être idempotente par conception. Une requête de lecture ne crée généralement pas ce problème. En revanche, un point de terminaison qui génère un nouvel objet ou mouvement à chaque appel a besoin d’une stratégie claire si ses utilisateurs peuvent réessayer.
L’idempotence a un coût : stockage des clés et des résultats, règles d’expiration, gestion de la concurrence et davantage de cas à tester. Ne l’ajoutez pas systématiquement à chaque point de terminaison. Donnez-lui la priorité lorsque les trois signes suivants sont réunis :
- L’opération peut produire un effet en double difficile ou coûteux à annuler.
- Le client ou l’infrastructure réessaie en cas de défaillance temporaire.
- La perte d’une réponse empêche de savoir si l’opération a été menée à bien.
Définissez également ce que signifie « même tentative » pour l’activité. Deux achats intentionnels similaires ne doivent pas être confondus simplement parce qu’ils ont le même montant et le même contenu. La déduplication doit s’appuyer sur une clé de tentative, et non sur une supposition concernant la similitude des requêtes.
Concevoir une clé : origine, unicité, portée et durée
En règle générale, le client génère une clé unique pour chaque opération logique et la conserve pendant toutes ses nouvelles tentatives. Il peut l’envoyer dans un en-tête convenu ou dans le corps de la requête, à condition que le contrat soit explicite. S’il génère une nouvelle clé à chaque tentative, le serveur ne pourra pas les relier. S’il réutilise une clé pour un nouvel achat, le serveur risque de bloquer une intention légitime.
La clé identifie la tentative, mais ne remplace ni l’authentification ni l’autorisation. Elle doit être associée à un périmètre, par exemple le compte ou le commerçant authentifié et le type d’opération. On évite ainsi qu’une coïncidence entre deux clients mélange leurs résultats. Le serveur doit vérifier ces limites à chaque requête.
Enregistrez également une empreinte de la requête normalisée : les champs qui déterminent l’effet, avec des règles stables pour les valeurs par défaut et leur représentation. Si une clé existe déjà et qu’une requête au contenu incompatible arrive, rejetez-la comme un conflit ; ne la traitez pas comme une nouvelle tentative valide et n’exécutez pas son contenu. L’empreinte doit exclure les données sans importance, mais conserver les détails qui changent l’intention, comme le montant ou la devise.
La durée dépend du comportement des clients, des files d’attente et des processus de reprise. Une fenêtre trop courte permet à une tentative tardive de répéter l’effet ; une fenêtre trop longue accumule les enregistrements et peut empêcher des réutilisations légitimes. Définissez une période adaptée à la durée maximale raisonnable des nouvelles tentatives et indiquez ce qui se passe ensuite. Pour les opérations financières ou à fort impact, il peut être nécessaire de conserver une référence durable au résultat au-delà de la fenêtre opérationnelle.
Réponses aux clés répétées et aux requêtes en cours
Le contrat doit distinguer plusieurs situations. Si la clé correspond à une opération terminée et que l’empreinte est identique, le serveur peut renvoyer le résultat enregistré de l’opération initiale. Celui-ci comprend généralement le code et le corps pertinents, mais pas nécessairement tous les en-têtes de transport. La réponse devrait permettre au client d’identifier la ressource créée ou l’état obtenu.
Si l’opération associée à la clé est en cours, évitez d’en lancer une deuxième exécution. Vous pouvez répondre en indiquant que le traitement se poursuit, ou renvoyer un conflit temporaire invitant le client à consulter le résultat ou à réessayer plus tard. Le client a besoin d’une règle claire : combien de temps attendre, s’il doit conserver la même clé et comment obtenir le résultat final. Ne présentez pas comme réussie une opération qui n’a pas encore été confirmée.
Si la clé existe avec une empreinte différente, renvoyez une erreur explicite et ne modifiez pas l’enregistrement initial. Si la première exécution a échoué, définissez quelles erreurs doivent être enregistrées comme résultats définitifs et lesquelles permettent un nouveau traitement. Par exemple, une erreur de validation peut être définitive pour cette requête, tandis qu’une interruption avant la confirmation des effets peut autoriser une reprise. Il n’existe pas de politique universelle : elle doit refléter le moment où le système peut établir ce qui s’est passé.
Persistance, concurrence et effets dans d’autres systèmes
Lorsque la réservation de la clé et la création de l’effet local partagent une base de données, elles doivent être coordonnées de manière atomique. Une contrainte d’unicité sur le périmètre et la clé aide à empêcher deux requêtes simultanées de franchir toutes deux une vérification initiale. La logique doit gérer la collision et lire l’état créé par la requête gagnante, plutôt que de se fier uniquement à une séquence « rechercher puis insérer ».
Enregistrez des états compréhensibles, par exemple en cours, terminé, ou en échec récupérable ou définitif. Ajoutez des horodatages et une politique de reprise pour les enregistrements dont le traitement a été interrompu. Un verrou qui n’expire jamais peut bloquer des opérations ; un verrou qui expire sans contrôle peut permettre à deux travailleurs d’agir simultanément. Avant de reprendre le traitement, la procédure de récupération doit vérifier l’état de l’effet.
La transaction locale n’inclut pas automatiquement un prestataire de paiement ou un autre service distant. Si le système enregistre la commande puis échoue avant d’appeler le prestataire, ou si celui-ci traite le paiement et que la réponse se perd, il faut rapprocher les états. Lorsque cela convient, utilisez une boîte d’envoi transactionnelle pour publier le travail après la confirmation du changement local, et transmettez une référence stable au système externe s’il prend en charge la déduplication. Enregistrez les identifiants externes et prévoyez des consultations ou des rapprochements.
Ne promettez pas une exécution « exactement une fois » de bout en bout au seul motif qu’une clé existe. Des défaillances ambiguës peuvent survenir entre les réseaux, les bases de données et les prestataires. La garantie réelle doit préciser quels effets sont dédupliqués, dans quel périmètre, pendant combien de temps et quels cas nécessitent une intervention ou un rapprochement.
Erreurs fréquentes et liste de vérification

- Nouvelle clé à chaque tentative : le client doit conserver et réutiliser la clé de la tentative initiale.
- Clé globale sans périmètre : associez-la au client authentifié et à l’opération concernée.
- Contenu différent pour une même clé : comparez une empreinte et rejetez toute réutilisation incompatible.
- Expiration sans analyse des tentatives tardives : documentez la fenêtre et décidez comment reprendre les anciennes opérations.
- Réponse ambiguë en cas de concurrence : précisez comment consulter le résultat ou réessayer tant que la première requête est active.
- Compter sur la clé pour couvrir les systèmes externes : prévoyez des références, des rapprochements et la gestion des défaillances partielles.
Avant de publier le point de terminaison, vérifiez que le client génère une clé par intention et la conserve après un délai d’attente ; que deux requêtes simultanées avec la même clé ne dupliquent pas l’effet ; et qu’une même clé accompagnée de données différentes ne déclenche pas une nouvelle opération. Testez également les défaillances avant et après l’écriture, les redémarrages du processus, l’expiration et les réponses perdues.
Enfin, surveillez les indicateurs relatifs aux clés répétées, aux conflits d’empreinte, aux opérations bloquées et aux divergences avec les services externes. Ces signaux aident à détecter les erreurs d’intégration et à ajuster la durée de conservation. Une implémentation utile ne supprime pas les défaillances : elle précise ce qui peut être répété sans dupliquer les effets et propose une voie sûre pour résoudre les incertitudes restantes.
