Guide de déploiement

n8n out of memory : diagnostic et correction sur VPS

Déployer sur un VPS Cloud →

Tutoriel

n8n out of memory : diagnostic et correction sur VPS

Automatisation9 min de lecture7 étapes

Le message `FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory` coupe n8n sans avertissement préalable. Beaucoup d'équipes ajoutent de la RAM et constatent que rien ne change — parce que le plafond V8 est indépendant de la mémoire physique du serveur et qu'il faut le poser explicitement. Cet article détaille les trois causes réelles du crash OOM, la variable d'environnement qui corrige chacune, et la séparation worker/webhook qui élimine les rechutes.

Sommaire· Pourquoi n8n crashe en mémoire, et pas pour la raison qu'on croit1/8
  1. 01Pourquoi n8n crashe en mémoire, et pas pour la raison qu'on croit
  2. 02Signaux qui confirment un crash OOM n8n
  3. 03Prérequis avant d'intervenir
  4. 04Corriger l'OOM : du diagnostic à la configuration stable
  5. 05Limiter la taille des payloads d'exécution
  6. 06Configuration post-correction : variables d'environnement utiles
  7. 07Dépannage — erreurs réelles et leurs causes
  8. 08Ressources et prochaines étapes

Pourquoi n8n crashe en mémoire, et pas pour la raison qu'on croit

V8, le moteur JavaScript embarqué dans Node.js, dispose d'un plafond de heap indépendant de la RAM physique. Par défaut il oscille entre 512 Mo et 1,5 Go selon la version de Node et la plateforme — sur un VPS à 4 Go ou 8 Go, la machine n'est pas à court de mémoire, mais le processus V8, lui, l'est. Allouer plus de RAM au serveur ne change rien sans NODE_OPTIONS=--max-old-space-size.

Deuxième cause fréquente : en mode main (le mode par défaut), n8n exécute les workflows dans le même processus qui sert les webhooks et l'API. Un workflow lourd en données — transformation CSV, agrégation de plusieurs milliers de lignes, appel GPT en boucle — monopolise le heap pendant son exécution. Si plusieurs s'accumulent, le plafond V8 est atteint et le processus est tué.

Troisième cause, plus subtile : les jobs s'accumulent en mémoire quand le mode queue est activé sans workers dédiés. La queue (Redis ou BullMQ) déleste le main process des exécutions, mais si aucun worker ne consomme réellement les jobs, ceux-ci s'accumulent, les callbacks restent en attente et le heap grossit.

Signaux qui confirment un crash OOM n8n

  • Message de sortie exact : FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory dans les logs du conteneur (docker logs n8n)
  • Crash silencieux sous systemd : le service redémarre automatiquement sans laisser de trace si Restart=always est actif — vérifier journalctl -u n8n --since "1 hour ago"
  • OOM kill du noyau : dmesg | grep -i oom montre Killed process <pid> (node) avant le redémarrage, indépendamment de Node
  • Corrélation avec un workflow lourd : le crash survient toujours pendant les exécutions de type « traitement de fichier » ou « boucle sur plusieurs milliers d'items »
  • Heap stable pendant des heures puis pic soudain : un workflow déclenché périodiquement accumule des closures non libérées — le heap monte à chaque run et ne redescend pas complètement
  • Charge mémoire normale sur htop : la RAM système n'est pas saturée au moment du crash, ce qui confirme que le problème est V8, pas la machine

Prérequis avant d'intervenir

Ces étapes supposent que n8n tourne déjà sur votre VPS via Docker Compose. Si ce n'est pas le cas, l'article installer-n8n-vps couvre le déploiement complet depuis zéro — revenez ici une fois l'instance en place.

Ce qu'il vous faut pour appliquer les corrections :

- Accès SSH root au VPS et fichier docker-compose.yml éditable
- Mémoire disponible : un plafond V8 de 4 096 Mo (--max-old-space-size=4096) suppose au moins 6 Go de RAM sur le VPS pour laisser de la marge au système d'exploitation, aux workers et à Redis
- Redis déjà déployé si vous passez en mode queue — redis:7-alpine suffit pour un usage mono-VPS
- Version n8n 1.0 ou supérieure : la séparation main/worker est disponible depuis la version 0.214 mais n'est stable en production qu'à partir de 1.0
- Sauvegarde de la base de données avant toute modification du Compose — les tables de credentials et d'exécutions ne font pas partie de l'image Docker

Corriger l'OOM : du diagnostic à la configuration stable

  1. Confirmer la cause dans les logs

    Lisez les 200 dernières lignes du conteneur au moment du crash :

    docker logs n8n --tail 200 2>&1 | grep -E "FATAL|heap|OOM|Killed"

    Si vous voyez FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory, c'est un crash V8. Si vous voyez Killed seul sans message Node, c'est l'OOM killer du noyau — les deux peuvent coexister sur le même incident.

  2. Poser le plafond V8 dans la variable NODE_OPTIONS

    Dans votre docker-compose.yml, ajoutez la variable d'environnement NODE_OPTIONS sur le service n8n. La valeur recommandée selon la RAM du VPS :

    - VPS 4 Go : --max-old-space-size=2048
    - VPS 8 Go : --max-old-space-size=4096
    - VPS 16 Go : --max-old-space-size=8192

    Règle : réserver environ la moitié de la RAM disponible après système d'exploitation et services annexes (Redis, proxy). Ne pas dépasser 70 % de la RAM totale.

    services:
      n8n:
        image: n8nio/n8n:latest
        environment:
          - NODE_OPTIONS=--max-old-space-size=4096
          # ... autres variables

    Attention : Ne mettez pas NODE_OPTIONS à l'intérieur d'un span de backticks dans vos fichiers .env si vous utilisez la substitution de variables — la valeur doit être une chaîne littérale.

  3. Vérifier que la valeur est bien prise en compte

    Après docker compose up -d, vérifiez que Node lit bien le plafond :

    docker exec n8n node -e "const v8=require('v8'); console.log(v8.getHeapStatistics().heap_size_limit / 1024 / 1024, 'MB')"

    La valeur affichée doit approcher votre --max-old-space-size. Si elle affiche encore 512 ou 1500, la variable d'environnement n'est pas transmise au processus — vérifiez que NODE_OPTIONS est dans la section environment: du service, pas dans env_file: avec une valeur mal parsée.

  4. Passer en mode queue avec Redis

    Le mode main (défaut) exécute tout dans un seul processus. Pour les instances qui traitent plus de 20 workflows simultanés ou des payloads volumineux, séparez les rôles :

    services:
      redis:
        image: redis:7-alpine
        restart: unless-stopped
        volumes:
          - redis_data:/data
    
      n8n:
        image: n8nio/n8n:latest
        environment:
          - NODE_OPTIONS=--max-old-space-size=2048
          - EXECUTIONS_MODE=queue
          - QUEUE_BULL_REDIS_HOST=redis
          - QUEUE_BULL_REDIS_PORT=6379
        depends_on:
          - redis
        ports:
          - "5678:5678"
    
      n8n-worker:
        image: n8nio/n8n:latest
        command: worker
        environment:
          - NODE_OPTIONS=--max-old-space-size=4096
          - EXECUTIONS_MODE=queue
          - QUEUE_BULL_REDIS_HOST=redis
          - QUEUE_BULL_REDIS_PORT=6379
        depends_on:
          - redis
        scale: 2
    
    volumes:
      redis_data:

    Le service n8n devient le main process (API + interface + webhooks) avec un plafond modéré. Le service n8n-worker prend en charge les exécutions avec un plafond plus généreux. La directive scale: 2 lance deux workers — ajustez selon vos besoins.

  5. Séparer le webhook process si le trafic l'exige

    Sur les instances qui reçoivent beaucoup de webhooks en parallèle, le main process peut être saturé même sans exécuter de workflows. n8n propose un mode webhook dédié :

      n8n-webhook:
        image: n8nio/n8n:latest
        command: webhook
        environment:
          - NODE_OPTIONS=--max-old-space-size=1024
          - EXECUTIONS_MODE=queue
          - QUEUE_BULL_REDIS_HOST=redis
          - QUEUE_BULL_REDIS_PORT=6379
          - N8N_DISABLE_UI=true
        depends_on:
          - redis
        ports:
          - "5679:5678"

    Configurez ensuite votre reverse proxy pour router /webhook/ vers le port 5679 et le reste vers le port 5678 du main process. Le mode webhook est disponible depuis n8n 1.0.

  6. Activer le garbage collector explicite pour les workflows lourds

    Pour les workflows qui traitent des fichiers volumineux ou des boucles longues, vous pouvez aider V8 à libérer la mémoire plus agressivement :

    NODE_OPTIONS="--max-old-space-size=4096 --expose-gc"

    Cette option expose global.gc() — n8n peut l'appeler entre les étapes d'un workflow. À combiner avec le paramètre EXECUTIONS_DATA_SAVE_ON_SUCCESS=none si vous n'avez pas besoin de l'historique d'exécution : les données d'exécution conservées en mémoire représentent souvent 30 à 50 % du heap.

  7. Surveiller le heap après correction

    Installez un endpoint de métriques n8n pour observer l'évolution du heap sans avoir à intervenir à la main :

    N8N_METRICS=true
    N8N_METRICS_PREFIX=n8n_

    L'endpoint /metrics (port 5678) expose alors nodejs_heap_size_used_bytes et nodejs_heap_size_total_bytes, compatibles Prometheus. Un dashboard Grafana basique sur ces deux métriques vous alertera bien avant le prochain crash.

Limiter la taille des payloads d'exécution

Le paramètre EXECUTIONS_DATA_MAX_SIZE (en bytes, défaut : aucune limite) coupe une exécution avant qu'elle ne puisse faire déborder le heap. Valeur recommandée pour les instances généralistes : 16777216 (16 Mo). Un workflow qui dépasse ce seuil échoue proprement au lieu de tuer le processus entier. Combinez-le avec EXECUTIONS_DATA_PRUNE=true et EXECUTIONS_DATA_MAX_AGE=168 (une semaine) pour éviter l'accumulation des données d'exécution passées en base.

Configuration post-correction : variables d'environnement utiles

Une fois l'OOM résolu, ces variables consolidaent la stabilité de l'instance :

- N8N_DEFAULT_BINARY_DATA_MODE=filesystem — stocke les fichiers binaires sur disque plutôt qu'en mémoire ; indispensable pour les workflows qui manipulent des fichiers CSV ou PDF volumineux
- OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true — les exécutions manuelles (déclenchées depuis l'éditeur) passent aussi par les workers, évitant de peser sur le heap du main process pendant les tests
- N8N_RUNNERS_ENABLED=true et N8N_RUNNERS_MAX_CONCURRENCY=5 — active le task runner expérimental (n8n 1.10+) qui isole chaque exécution dans un sous-processus, empêchant un seul workflow de consommer tout le heap disponible
- DB_POSTGRESDB_* — migrer de SQLite à PostgreSQL sur les instances à fort volume : SQLite sérialise toutes les lectures/écritures et peut bloquer les workers, amplifiant la pression mémoire

Dépannage — erreurs réelles et leurs causes

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
Cause directe : le heap V8 a atteint son plafond. Solution : ajouter NODE_OPTIONS=--max-old-space-size=<n> dans les variables d'environnement du conteneur, avec une valeur calibrée sur la RAM disponible (voir étape 2).

Killed dans les logs, sans message Node
Cause : l'OOM killer du noyau Linux a terminé le processus avant que V8 ne puisse émettre son message. Survient quand la mémoire physique est effectivement épuisée — différent du crash V8 pur. Vérifier avec dmesg | grep -i oom. Réduire --max-old-space-size ou ajouter de la RAM, et activer EXECUTIONS_DATA_SAVE_ON_SUCCESS=none pour alléger l'empreinte.

Les workers ne consomment pas les jobs malgré EXECUTIONS_MODE=queue
Cause fréquente : DB_TYPE et les variables de base de données ne sont pas transmises aux workers. Chaque service du Compose doit avoir ses propres variables de connexion — le worker n'hérite pas de la configuration du main process. Vérifiez avec docker exec n8n-worker env | grep DB_.

Le heap grimpe après chaque run et ne redescend pas
Cause : une closure retient une référence à un grand tableau entre les exécutions. Activer --expose-gc dans NODE_OPTIONS et ajouter EXECUTIONS_DATA_SAVE_ON_SUCCESS=none pour éviter que les données d'exécution ne s'accumulent. Si le comportement persiste, passer en mode task runner (N8N_RUNNERS_ENABLED=true) qui isole chaque workflow.

Error: Redis connection failed après le passage en mode queue
Cause : QUEUE_BULL_REDIS_HOST pointe vers localhost au lieu du nom de service Docker. Dans un réseau Compose, le main process et les workers atteignent Redis par son nom de service (redis dans l'exemple ci-dessus), pas par 127.0.0.1.

Ressources et prochaines étapes

La documentation officielle n8n sur les erreurs mémoire (docs.n8n.io/hosting/scaling/memory-errors) détaille les valeurs recommandées de --max-old-space-size selon la RAM disponible et liste les paramètres de scaling. L'issue GitHub n8n-io/n8n#17461 (OOM en production, ouverte en mars 2026, 80+ commentaires) documente des cas réels — notamment la corrélation entre workflows de traitement CSV et crash heap — et les configurations qui ont stabilisé des instances similaires à la vôtre.

Si vous gérez plusieurs instances n8n pour des clients différents, la séparation main/worker décrite ici est aussi la base d'une architecture multi-tenant : chaque client peut avoir son propre pool de workers avec un plafond V8 indépendant, sans qu'un workflow lourd d'un compte n'impacte les autres.

Déployez n8n sur un VPS dédié

Un VPS avec accès root, IPv4 dédiée et choix d'OS pour héberger votre instance n8n en mode queue, sans restriction de workflows ni de webhooks.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet