Race conditions dans n8n : empêcher un workflow de s’exécuter en double sur lui-même
Publié le 1 septembre 2026 · 6 min de lecture
Un client valide une réservation sur un formulaire. Au même instant, presque à la milliseconde près, un second client valide la même réservation depuis un autre onglet resté ouvert. Les deux webhooks arrivent sur la même instance n8n à quelques millisecondes d’écart, déclenchent chacun une exécution du même workflow, et les deux lisent « créneau disponible » avant que l’une ou l’autre n’ait eu le temps d’écrire « créneau pris ». Résultat : deux confirmations envoyées pour une seule place. Ce n’est pas un bug du workflow — c’est une race condition, un problème structurel qui touche n8n exactement comme n’importe quel système qui traite des requêtes en parallèle.
Ce que la limite de concurrence de n8n fait vraiment
n8n expose un réglage de concurrence via la variable d’environnement N8N_CONCURRENCY_PRODUCTION_LIMIT, disponible aussi bien en mode régulier qu’en mode queue. Fixée à -1 (illimité) par défaut, elle peut être réglée à un nombre entier : au-delà de ce plafond, les nouvelles exécutions de production sont mises en file d’attente FIFO plutôt que lancées immédiatement. Trois précisions changent tout pour l’usage qu’on peut en attendre :
- Elle s’applique uniquement aux exécutions de production — celles démarrées par un webhook ou un trigger. Les exécutions manuelles, les sous-workflows et les exécutions d’erreur ne sont pas comptés.
- Elle plafonne l’instance entière, tous workflows confondus — pas un workflow en particulier. Un plafond de 10 protège le serveur d’une surcharge globale, mais n’empêche en rien deux déclenchements du même workflow de tourner en parallèle si l’instance est par ailleurs peu chargée.
- Elle ne connaît rien de la ressource métier manipulée à l’intérieur du workflow. Deux exécutions parfaitement autorisées par la limite de concurrence peuvent très bien écrire, en même temps, sur la même ligne de stock ou le même créneau de calendrier.
Autrement dit : N8N_CONCURRENCY_PRODUCTION_LIMIT est un régulateur de trafic pour l’instance, pas un verrou pour un workflow donné. n8n ne propose pas, à ce jour, de réglage natif du type « n’autoriser qu’une seule exécution à la fois de ce workflow précis » — c’est au workflow lui-même de se protéger.
Pourquoi vérifier avant d’écrire ne suffit pas
Le réflexe naturel consiste à ajouter un node IF qui vérifie l’état de la ressource avant de la modifier — « ce créneau est-il déjà pris ? ». Le problème est que la lecture et l’écriture ne forment pas une seule opération atomique dans un workflow n8n classique : il s’écoule un temps, même bref, entre le node qui lit l’état et celui qui écrit le nouveau. Si une seconde exécution lit l’état exactement dans cette fenêtre, elle voit encore l’ancienne valeur et prend la même décision. Plus le workflow contient d’appels HTTP entre la lecture et l’écriture (enrichissement, appel à un LLM, envoi d’un email de confirmation), plus cette fenêtre s’élargit et plus la collision devient probable — c’est exactement le mécanisme qui rend possibles les conflits de réservation calendrier que nous avons documentés récemment, sauf qu’ici les deux écritures viennent du même workflow plutôt que de deux outils différents.
Une étude de chercheurs en cybersécurité de l’université de Cagliari, publiée en 2025 dans Computers & Security, a précisément mesuré les facteurs qui rendent une race condition exploitable dans une application web — délai entre la lecture et l’écriture, latence réseau, protocole HTTP utilisé — et montre que la fenêtre nécessaire pour déclencher une collision peut se compter en quelques millisecondes seulement, largement à la portée de deux requêtes envoyées à quelques instants d’intervalle (Loi, Pisu, Regano, Maiorca & Giacinto, 2025, Race Against Time: Investigating the Factors that Influence Web Race Condition Exploits, Computers & Security). Le contexte de l’étude est la sécurité offensive, mais le mécanisme qu’elle quantifie est identique à celui qui produit un double-booking ou un stock survendu dans un workflow d’automatisation : ce n’est pas la vitesse du workflow qui protège, c’est l’atomicité de l’opération critique.
Construire un verrou avec une Data Table
La solution qui règle le problème à la racine est un verrou applicatif : avant de traiter une ressource, le workflow tente de poser un verrou dessus ; s’il y parvient, il traite et le libère ; sinon, il attend ou abandonne. Les Data Tables de n8n sont un support naturel pour ça, sans base externe à provisionner :
- Une table
verrousavec deux colonnes :ressource_id(la clé, par exemple l’identifiant du créneau ou de l’article) etverrouille_le(horodatage de pose du verrou). - À l’entrée du workflow, un node Data Table tente d’insérer une ligne pour cette
ressource_id. Une contrainte d’unicité sur la colonne fait échouer l’insertion si une ligne existe déjà — c’est cet échec, et non une lecture préalable, qui sert de test : l’opération d’insertion elle-même est atomique côté base, contrairement à un couple lecture-puis-écriture. - Si l’insertion réussit, le workflow a le verrou : il traite la réservation ou la commande, puis supprime la ligne de la table en fin de traitement (ou dans l’Error Workflow si une erreur survient, pour ne jamais laisser un verrou orphelin).
- Si l’insertion échoue, une autre exécution détient déjà le verrou : le node Wait patiente quelques secondes puis retente, ou le workflow s’arrête proprement en signalant le conflit plutôt que de traiter une ressource déjà prise.
Un détail à ne pas manquer : toujours ajouter un délai d’expiration au verrou (par exemple, ignorer toute ligne dont verrouille_le date de plus de deux minutes) pour qu’une exécution plantée avant l’étape de libération ne bloque pas indéfiniment la ressource pour tout le monde.
Ce que Dijkstra avait déjà résolu en 1965
Le principe n’a rien de nouveau : c’est exactement le problème de l’exclusion mutuelle formalisé par Edsger Dijkstra dans un article fondateur de l’informatique, Solution of a Problem in Concurrent Programming Control, Communications of the ACM, 1965, qui pose les bases de ce que tout système concurrent doit garantir : qu’une seule exécution à la fois accède à une section critique, sans dépendre de l’ordre d’arrivée ni de la vitesse relative des processus. Un workflow n8n qui modifie une ressource partagée est, ni plus ni moins, un processus concurrent — la Data Table joue simplement le rôle du verrou que Dijkstra décrivait pour des processus système, soixante ans avant l’arrivée du no-code.
Cas d’usage concrets
- Décrément de stock e-commerce. Deux commandes pour le dernier exemplaire d’un article, arrivées via deux canaux (site web et marketplace), traitées par le même workflow n8n : sans verrou, les deux peuvent lire « 1 en stock » et confirmer la vente en double.
- Webhooks Stripe retraités. Un webhook Stripe qui échoue en HTTP peut être renvoyé automatiquement par Stripe — le verrou sur l’identifiant de la facture évite de générer deux fois le même document, en complément de l’idempotence déjà recommandée sur les webhooks.
- Génération de documents séquentiels. Un workflow qui attribue un numéro de facture ou de devis incrémental à partir d’un compteur doit impérativement verrouiller le compteur le temps de l’incrémenter et de l’enregistrer, sous peine d’attribuer deux fois le même numéro à deux documents différents.
Pièges à éviter
- Confondre limite de concurrence et verrou métier :
N8N_CONCURRENCY_PRODUCTION_LIMITprotège l’instance, pas une ressource précise. - Vérifier puis écrire en deux étapes séparées au lieu de s’appuyer sur une opération atomique (insertion avec contrainte d’unicité) pour poser le verrou.
- Oublier l’expiration du verrou : une exécution qui plante avant de le libérer bloque la ressource indéfiniment pour toutes les suivantes.
- Verrouiller une ressource trop large (« tout le stock » plutôt que « cet article précis ») — cela élimine la race condition mais sérialise inutilement des traitements qui n’entrent jamais en conflit entre eux.
En résumé
N8N_CONCURRENCY_PRODUCTION_LIMIT régule le trafic d’une instance n8n, mais ne protège aucune ressource métier précise contre deux exécutions simultanées du même workflow. La seule protection fiable est un verrou applicatif, construit avec une Data Table et une contrainte d’unicité qui rend la pose du verrou atomique — un principe vieux de soixante ans, appliqué avec les outils no-code d’aujourd’hui. Les workflows de traitement de commandes et de facturation du Pack Conformité & Audit (149 €) suivent cette même logique de verrouillage sur les opérations séquentielles sensibles ; si votre instance combine déjà plusieurs de ces automatisations à fort enjeu, le Bundle FlowKit Complet (269 € au lieu de 347 €) réunit l’ensemble des packs pour les faire cohabiter sur une base commune.
FAQ
Questions fréquentes
N8N_CONCURRENCY_PRODUCTION_LIMIT empêche-t-il deux exécutions simultanées d’un même workflow ?
Non directement. Cette variable plafonne le nombre total d’exécutions de production actives sur toute l’instance, tous workflows confondus — elle ralentit le débit global mais n’empêche pas deux déclenchements du même workflow, sur la même ressource, de tourner en parallèle si le plafond n’est pas atteint. C’est un frein de trafic, pas un verrou métier.
Le mode queue de n8n résout-il le problème de concurrence ?
Le mode queue répartit les exécutions entre plusieurs workers et permet de régler N8N_CONCURRENCY_PRODUCTION_LIMIT par worker, ce qui aide à absorber une charge élevée sans surcharger l’instance. Mais la variable reste un plafond global : elle ne garantit toujours pas qu’une ressource précise (un créneau, une ligne de stock, une facture) ne soit traitée que par une seule exécution à la fois.
Pourquoi ne pas simplement vérifier l’état de la ressource avant de la modifier ?
Parce que la vérification et la modification ne sont pas une seule opération atomique dans un workflow n8n classique : entre le node qui lit l’état (« ce créneau est libre ») et le node qui écrit le nouvel état, une autre exécution peut lire exactement le même état avant que la première n’ait écrit sa mise à jour. C’est précisément ce délai qui définit une race condition, quelle que soit la rapidité du workflow.
Bundle FlowKit Complet
269 €