Qu'est-ce que l'idempotence ?

En informatique, l'idempotence est la propriété d'une opération dont l'exécution répétée a le même résultat final que si elle n'avait été appliquée qu'une seule fois. Si vous envoyez cinq fois la même requête à un serveur, un système idempotent garantit que l'état du serveur reste inchangé après la première tentative réussie.

En plus de garantir le même résultat, les opérations idempotentes ont pour caractéristique essentielle de ne produire aucun effet secondaire lors des appels supplémentaires. C'est une condition essentielle à la conception de systèmes distribués résilients, où des interruptions de réseau intermittentes ou des délais d'expiration peuvent amener un client à envoyer plusieurs fois le même message.

Analogie : pensez au bouton d'appel d'un ascenseur. Appuyez une fois, et l'ascenseur est appelé à votre étage. Si vous appuyez dix fois de plus sur le bouton en attendant, le résultat est le même : un seul ascenseur arrive à votre étage. Appuyer plusieurs fois sur le bouton ne fait pas venir dix ascenseurs différents. À l'inverse, ajouter un article à un panier d'achat en ligne n'est généralement pas une opération idempotente. Si vous cliquez cinq fois sur le bouton "Ajouter au panier", vous aurez probablement cinq exemplaires de cet article dans votre panier.

Principaux avantages des systèmes idempotents

Relancez les requêtes en toute sécurité après un délai d'expiration ou une coupure de connexion, sans risque de dupliquer des actions (comme débiter deux fois une carte de crédit).

Les utilisateurs n'ont pas besoin d'un système complexe de suivi d'état pour savoir si une requête précédente a réussi ; il leur suffit de "réessayer jusqu'à ce qu'elle aboutisse".

Les systèmes distribués peuvent se rétablir après un plantage en rejouant les journaux ou en renvoyant les messages manqués, sans corrompre les données.

Méthodes HTTP idempotentes et non idempotentes

La norme REST définit le comportement des différents types de requêtes Web. Certaines méthodes HTTP sont naturellement "sûres" ou idempotentes par conception, ce qui signifie que la spécification prévoit qu'elles se comportent de manière prévisible, même lorsqu'elles sont répétées. D'autres servent à créer des données et nécessitent une attention particulière pour pouvoir être réutilisées sans risque.

Méthodes idempotentes (GET, PUT, DELETE)

Selon la RFC 9110, plusieurs méthodes standards sont intrinsèquement idempotentes. La répétition de ces actions ne doit pas modifier l'état du serveur au-delà de la requête initiale.

  • GET : cette méthode permet de récupérer des données. Comme elle n'entraîne aucune modification sur le serveur, vous pouvez l'appeler un million de fois sans que la ressource ne change.
  • PUT : cette méthode remplace intégralement une ressource. Si vous mettez à jour l'adresse e-mail d'un utilisateur trois fois pour la définir sur "utilisateur@exemple.com", l'état final est toujours "utilisateur@exemple.com".
  • DELETE : supprime une ressource. Si vous supprimez la commande n° 123, puis que vous tentez de la supprimer à nouveau, elle reste supprimée. Le résultat (la commande a disparu) reste le même.

Méthodes non idempotentes (POST, PATCH)

Certaines méthodes ne sont pas idempotentes, car leur rôle principal consiste à modifier les données afin de créer une nouvelle ressource ou de mettre à jour une partie d'un enregistrement existant.

  • POST : les développeurs utilisent POST pour créer des ressources. Sans logique d'idempotence, l'envoi de deux requêtes POST identiques (comme "Envoyer le paiement") créerait généralement deux enregistrements distincts et facturerait donc le client deux fois.
  • PATCH : cette méthode applique des mises à jour partielles. Bien qu'elle puisse être rendue idempotente, elle ne l'est souvent pas par défaut, car la répétition d'une modification relative (comme "ajouter 5 au solde") produirait une valeur finale différente à chaque appel.

Implémenter une API idempotente

  1. Générer une clé unique : le client crée une chaîne unique (comme un UUID) et l'inclut dans un en-tête HTTP personnalisé.
  2. Intercepter et valider : le serveur vérifie dans un datastore à haut débit comme Memorystore si cette clé a été traitée récemment.
  3. Gérer l'état : si la clé est nouvelle, traitez la requête et enregistrez le résultat. S'il s'agit d'un doublon, renvoyez immédiatement le résultat stocké sans réexécuter la logique métier.

Cas d'utilisation courants de l'idempotence

L'idempotence est souvent nécessaire dans les systèmes que nous créons. Dans certains cas, elle est gérée automatiquement. Dans d'autres cas, c'est à nous, développeurs, d'intervenir pour la mettre en œuvre.

L'exemple le plus connu est le problème de la double facturation. Si le navigateur d'un utilisateur se bloque au moment de payer un vol, l'utilisateur risque de cliquer à nouveau sur "Payer". Une API de paiement qui utilise une clé d'idempotence garantit que le deuxième clic est reconnu comme une nouvelle tentative. Cela protège le compte bancaire du client et réduit les coûts opérationnels liés au traitement des remboursements pour les transactions en double.

  • Action requise de la part du développeur : vous devez implémenter une clé d'idempotence (souvent un UUID) dans votre requête API pour que le deuxième clic soit reconnu comme une nouvelle tentative, ce qui protège le compte bancaire du client.

Des outils comme Terraform et Ansible reposent sur l'idempotence. Lorsque vous exécutez un script pour "créer un bucket de stockage de 10 Go", l'outil vérifie l'état actuel de votre cloud.

  • Gestion automatique : l'idempotence est gérée par l'outil IaC lui-même. En tant que développeur, vous n'avez pas besoin d'écrire de logique supplémentaire pour éviter les ressources en double.

Les API Web modernes implémentent souvent l'en-tête Idempotency-Key (désormais un projet IETF standardisé) pour permettre aux développeurs de créer des intégrations plus robustes.

  • Action requise de la part du développeur : lors de la création du backend, vous devez implémenter la logique permettant d'intercepter ces clés, de vérifier si des tentatives ont déjà été effectuées et de renvoyer la réponse mise en cache.

Une opération "upsert" (mise à jour ou insertion) est une opération de base de données idempotente classique. Au lieu d'une simple insertion, une opération upsert indique : "Si cet enregistrement existe, mettez-le à jour. Sinon, créez-le."

  • Gestion automatique : cette logique est gérée nativement par le moteur de base de données, assurant ainsi que les enregistrements convergent vers l'état correct, quel que soit le nombre d'exécutions du script.

Relevez vos plus grands défis avec Google Cloud

Les nouveaux clients bénéficient de 300 $ de crédits à dépenser sur Google Cloud.
Contactez un spécialiste des ventes Google Cloud pour discuter plus en détail de votre problématique.

Créer des microservices fiables sur Google Cloud

Google Cloud propose plusieurs outils qui facilitent l'implémentation de ces modèles pour les développeurs. Développer sur une plate-forme gérée réduit la quantité de code récurrent que vous devez écrire pour assurer la sécurité de vos données.

  • Cloud Run : lorsque vous utilisez Cloud Run pour traiter des événements issus de Pub/Sub, n'oubliez pas que Pub/Sub peut distribuer des messages plusieurs fois par défaut. Vous devez écrire du code idempotent dans vos services Cloud Run pour vous assurer que vos agents IA ou vos pipelines de données ne traitent pas deux fois le même événement.
  • Remarque concernant Pub/Sub : la distribution par défaut est basée sur le Push, mais la distribution de type "exactement une fois" est disponible pour les abonnements basés sur le Pull. Il est utile de connaître ces deux types pour choisir le niveau de complexité adapté à votre service.

Prêt à créer ?

Découvrez comment déployer des services résilients et idempotents sur Cloud Run dès aujourd'hui.

Google Cloud