FlowKit

getWorkflowStaticData dans n8n : stocker un état entre deux exécutions

Publié le 1 août 2026 · 7 min de lecture

Un workflow n8n est amnésique par défaut : chaque exécution démarre de zéro, sans souvenir de la précédente. C'est un problème dès qu'un workflow doit savoir « où il en était » — dernier article RSS traité, dernier ID récupéré d'une API, token mis en cache. La fonction $getWorkflowStaticData() répond exactement à ce besoin : un petit espace de stockage persistant, attaché au workflow, qui survit d'une exécution à l'autre. Ce guide couvre la syntaxe dans le node Code, les cas d'usage légitimes, le piège qui fait perdre des heures à presque tout le monde (les exécutions de test ne sauvegardent rien), et les alternatives quand le mécanisme atteint ses limites.

À quoi sert le static data

Le static data est fait pour stocker un état de travail léger entre deux exécutions du même workflow :

  • Curseur de dernière exécution : le timestamp du dernier passage, pour ne récupérer que les éléments apparus depuis (« donne-moi tout ce qui est postérieur à X »).
  • Dernier identifiant traité : l'ID le plus élevé déjà vu lors d'un polling incrémental d'API, de base de données ou de flux.
  • Cache léger : un token d'accès obtenu par un appel d'authentification, réutilisé tant qu'il n'a pas expiré, plutôt que redemandé à chaque exécution.
  • Déduplication simple : une courte liste de clés déjà traitées, pour ignorer les éléments revus — en complément des approches décrites dans notre guide sur l'idempotence des webhooks et l'évitement des doublons.

Ce besoin de mémoriser un point de reprise n'a rien d'anecdotique. Une étude de Paris Carbone, Stephan Ewen et leurs co-auteurs, « State Management in Apache Flink: Consistent Stateful Distributed Stream Processing », publiée en 2017 dans les Proceedings of the VLDB Endowment, montre que la gestion d'un état persistant et cohérent (snapshots, curseurs, points de reprise) est la pierre angulaire des moteurs de traitement de flux modernes — un traitement sans mémoire ne peut être ni incrémental ni fiable. Le static data de n8n en est la version miniature : un état minimal, sauvegardé à la fin de chaque exécution réussie.

Syntaxe dans le node Code : 'global' vs 'node'

Le static data se manipule dans un node Code (JavaScript), avec les mêmes réflexes que ceux détaillés dans notre guide des expressions et du JavaScript dans le node Code :

// Espace partagé par tous les nodes du workflow
const staticData = $getWorkflowStaticData('global');

// Lecture (avec valeur par défaut au premier passage)
const lastRun = staticData.lastRun ?? 0;

// Écriture : il suffit de modifier l'objet, n8n le sauvegarde
// automatiquement à la fin de l'exécution
staticData.lastRun = Date.now();

return $input.all();

Deux portées existent :

  • $getWorkflowStaticData('global') : un seul objet partagé par tous les nodes du workflow. Simple, mais deux nodes qui écrivent la même clé s'écrasent mutuellement.
  • $getWorkflowStaticData('node') : un espace propre au node courant. Deux nodes Code peuvent chacun avoir leur clé lastId sans conflit — le bon choix dès qu'un workflow gère plusieurs curseurs indépendants.

Point important : il n'y a aucune fonction « save » à appeler. Vous mutez l'objet retourné, et n8n persiste son contenu à la fin de l'exécution. C'est élégant, mais c'est aussi la source du piège suivant.

Le piège n°1 : rien n'est sauvegardé en exécution de test

C'est la cause de la quasi-totalité des messages « getWorkflowStaticData ne marche pas » : les données statiques ne sont pas persistées lors des exécutions manuelles lancées avec le bouton d'exécution de l'éditeur. Pendant un test, vous pouvez lire le static data existant et le modifier en mémoire, mais à la fin de l'exécution, rien n'est écrit en base. Seules les exécutions de production — déclenchées par un webhook, un Schedule Trigger, un trigger d'application, sur un workflow activé — sauvegardent l'état.

Conséquences pratiques :

  1. Pour tester une logique de curseur, activez le workflow et déclenchez-le réellement (appel du webhook de production, prochain tick du Schedule Trigger), puis inspectez l'exécution dans l'historique.
  2. Prévoyez toujours une valeur par défaut (?? 0, ?? null) : au premier passage en production, l'objet est vide.
  3. Ne concluez jamais qu'un curseur « ne s'incrémente pas » sur la foi d'un test manuel : c'est le comportement attendu, pas un bug.

Les autres pièges à connaître

Import, export et duplication du workflow

Le static data est attaché à l'enregistrement du workflow dans la base de données de votre instance, pas au fichier JSON que vous manipulez. Quand vous dupliquez un workflow, ou l'exportez puis le réimportez ailleurs, la copie repart avec un état vide : le curseur revient à zéro et le workflow retraitera tout l'historique au prochain déclenchement. Gardez ce point en tête lors des migrations — notre guide sur l'import et l'export de workflows n8n détaille ce qui voyage dans le JSON et ce qui reste en base.

Mode queue et exécutions concurrentes

En mode queue avec Redis et plusieurs workers, chaque exécution charge le static data au démarrage et le sauvegarde à la fin. Si deux exécutions tournent en parallèle, la dernière à se terminer écrase les écritures de l'autre : ni verrou, ni fusion. Pour un Schedule Trigger horaire, aucun risque ; pour un webhook qui reçoit des rafales d'événements simultanés, le static data n'est pas le bon outil — passez à un stockage externe transactionnel.

La taille : un curseur, pas un entrepôt

Le static data est stocké en base avec le workflow, relu puis réécrit à chaque exécution. Il est conçu pour quelques clés légères — un timestamp, un ID, un petit objet. Y accumuler des milliers d'entrées (liste d'IDs qui grossit indéfiniment, réponses d'API complètes) alourdit chaque exécution et fait gonfler la base. Si votre liste de déduplication grandit sans limite, tronquez-la (gardez les N dernières clés) ou changez d'outil.

Exemple concret : veille RSS sans doublons

Le cas d'école, dans l'esprit de notre guide de veille RSS automatisée avec n8n : un Schedule Trigger lit un flux toutes les heures, et seuls les articles réellement nouveaux doivent partir vers Slack ou Notion.

const staticData = $getWorkflowStaticData('node');
const lastSeen = staticData.lastSeen ?? 0;

const newItems = $input.all().filter((item) => {
  const published = new Date(item.json.pubDate).getTime();
  return published > lastSeen;
});

if (newItems.length > 0) {
  staticData.lastSeen = Math.max(
    ...newItems.map((i) => new Date(i.json.pubDate).getTime())
  );
}

return newItems;

Au premier déclenchement en production, tout passe (curseur à 0) ; ensuite, seuls les articles publiés après le dernier passage sont transmis. Le même pattern s'applique au polling incrémental d'une API : stockez le plus grand id ou le updated_at le plus récent, puis interrogez l'API avec un paramètre du type ?since={{ curseur }} — les éléments déjà vus ne sont même plus téléchargés.

À noter : pour la déduplication pure, le node Remove Duplicates propose une option qui mémorise les éléments vus lors des exécutions précédentes, sans écrire une ligne de code — notre guide du node Remove Duplicates compare les deux approches.

Quand le static data ne suffit plus

Trois signaux indiquent qu'il faut passer à un vrai stockage :

  • Volume : plus de quelques dizaines de clés, ou des listes qui grossissent à chaque exécution.
  • Concurrence : plusieurs exécutions simultanées qui doivent lire et écrire le même état sans se perdre des écritures.
  • Partage : un état consulté par plusieurs workflows, ou qui doit survivre à une migration d'instance.

Les alternatives, par ordre de simplicité :

  1. Les Data Tables n8n : des tables natives, gérées dans l'interface, lisibles et modifiables par n'importe quel workflow — le premier réflexe quand on dépasse le stade du simple curseur. Voir notre guide des Data Tables n8n.
  2. Redis : clés à expiration automatique (parfait pour un cache de token), compteurs atomiques, verrous — idéal pour la déduplication sous forte concurrence.
  3. Une table Supabase ou PostgreSQL : état durable, requêtable, partagé entre workflows et instances, avec l'historique en prime — notre guide pour connecter n8n à Supabase couvre la mise en place.

En résumé

$getWorkflowStaticData('global') (partagé) ou 'node' (isolé par node) offre un état persistant entre exécutions, sauvegardé automatiquement à la fin de chaque run — mais uniquement en exécution de production, jamais lors d'un test manuel : c'est le piège numéro un. L'état vit en base avec le workflow, disparaît à la duplication ou au réimport, ne gère pas la concurrence du mode queue et doit rester léger. Pour tout le reste — volumes, écritures concurrentes, état partagé — basculez vers les Data Tables, Redis ou une table Postgres. Bien utilisé, c'est l'outil le plus simple de n8n pour transformer un workflow amnésique en traitement incrémental fiable.

FAQ

Questions fréquentes

Pourquoi mon static data n8n reste vide quand je teste le workflow ?

Parce que les données statiques ne sont pas sauvegardées lors des exécutions de test manuelles (bouton Execute workflow dans l'éditeur). Elles ne sont persistées qu'à la fin d'une exécution de production, déclenchée par un vrai trigger : webhook, Schedule Trigger, événement d'application. Pour vérifier que votre logique fonctionne, activez le workflow et déclenchez-le réellement, puis inspectez l'exécution dans l'historique.

Où n8n stocke-t-il les données de getWorkflowStaticData ?

Dans la base de données de l'instance n8n, avec l'enregistrement du workflow lui-même (SQLite ou PostgreSQL selon votre installation). C'est pour cette raison qu'il faut y stocker des valeurs légères — un timestamp, un identifiant, quelques clés — et non des lots de données volumineux, qui seraient relus et réécrits à chaque exécution.

Comment réinitialiser le static data d'un workflow n8n ?

Depuis un node Code, supprimez les clés concernées (delete staticData.maCle) ou réassignez-les, puis laissez le workflow se terminer via une exécution de production — une exécution manuelle ne sauvegardera pas la remise à zéro. Autre option radicale : dupliquer le workflow, la copie repart avec un static data vide.

Quelle est la différence entre $getWorkflowStaticData('global') et 'node' ?

Avec 'global', tous les nodes du workflow lisent et écrivent le même objet partagé. Avec 'node', chaque node dispose de son propre espace isolé : deux nodes Code peuvent utiliser la même clé lastId sans se marcher dessus. Préférez 'node' dès qu'un workflow contient plusieurs compteurs ou curseurs indépendants.

Bundle FlowKit Complet

269 €