FlowKit

n8n et PostgreSQL : configurer la base et migrer depuis SQLite sans rien perdre

Publié le 5 août 2026 · 6 min de lecture

Par défaut, une instance n8n self-hosted stocke tout — workflows, credentials chiffrés, historique des exécutions — dans un simple fichier SQLite posé dans /home/node/.n8n. C'est un choix parfaitement raisonnable pour démarrer : zéro configuration, zéro service supplémentaire. Mais dès que l'instance devient sérieuse — des centaines d'exécutions par jour, des workflows IA gourmands, un passage au mode queue — ce fichier unique devient le facteur limitant. Ce guide couvre les deux étapes du passage à PostgreSQL : la configuration propre (variables d'environnement, docker-compose) et la migration des données existantes depuis SQLite, sans perdre ni workflows ni credentials.

SQLite par défaut : très bien pour débuter, jusqu'au jour où ça coince

SQLite n'est pas une base « au rabais » : c'est le moteur de base de données le plus déployé au monde, présent dans à peu près chaque smartphone et navigateur, comme le rappellent Gaffney, Prammer, Hipp, Patel et leurs co-auteurs dans leur article de 2022 publié au VLDB, « SQLite: Past, Present, and Future » (voir l'étude sur Google Scholar). Sa force est justement son design in-process : la base vit dans le même processus que l'application, sans serveur séparé.

C'est aussi sa limite pour n8n. Concrètement, le basculement vers PostgreSQL s'impose quand :

  • Le volume d'exécutions explose. Chaque exécution écrit ses données dans la base ; un fichier SQLite de plusieurs Go ralentit l'interface et complique le nettoyage des exécutions.
  • Les écritures concurrentes se multiplient. SQLite sérialise les écritures : un seul writer à la fois. Des webhooks fréquents plus des schedules simultanés finissent en contention. Les SGBD client-serveur comme PostgreSQL sont précisément architecturés pour la concurrence — gestion des verrous, MVCC, pool de connexions — comme le détaille l'article de référence de Hellerstein, Stonebraker et Hamilton, « Architecture of a Database System » (2007) (voir sur Google Scholar).
  • Vous passez en mode queue. Le mode queue avec Redis et des workers exige une base partagée entre le processus principal et les workers : SQLite n'y est pas supporté, PostgreSQL est requis.
  • Vous voulez des sauvegardes à chaud fiables. pg_dump produit un instantané cohérent pendant que n8n tourne ; copier un fichier SQLite en cours d'écriture risque la corruption.

Les variables d'environnement qui basculent n8n sur PostgreSQL

Toute la configuration passe par des variables d'environnement (le mécanisme général est détaillé dans notre guide des variables d'environnement n8n) :

DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres        # nom du service Docker ou hostname
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=un_mot_de_passe_fort
DB_POSTGRESDB_SCHEMA=public        # optionnel, "public" par défaut

Piège classique : si DB_TYPE est absent ou mal orthographié (postgres au lieu de postgresdb), n8n ne renvoie pas d'erreur — il retombe silencieusement sur SQLite et vous découvrez des semaines plus tard que la base PostgreSQL est restée vide. Vérifiez toujours les logs de démarrage.

docker-compose complet : n8n + PostgreSQL

Le montage type, avec volume persistant, healthcheck et démarrage ordonné (si vous partez de zéro, commencez par notre guide d'installation de n8n avec Docker) :

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=un_mot_de_passe_fort
      - POSTGRES_DB=n8n
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=un_mot_de_passe_fort
      - DB_POSTGRESDB_SCHEMA=public
      - N8N_ENCRYPTION_KEY=votre_cle_existante
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  postgres_data:
  n8n_data:

Le condition: service_healthy évite le crash au premier démarrage : n8n n'essaie de se connecter qu'une fois PostgreSQL réellement prêt, pas juste lancé. Le volume n8n_data reste utile même sur PostgreSQL : n8n y conserve des fichiers de configuration locaux.

N8N_ENCRYPTION_KEY : la variable qui décide si vos credentials survivent

C'est le point qui transforme une migration tranquille en week-end de ressaisie manuelle. Les credentials sont chiffrés avec la clé N8N_ENCRYPTION_KEY, générée au premier démarrage et stockée dans le fichier ~/.n8n/config si vous ne l'avez pas définie explicitement. Changer de base de données ne change rien au chiffrement : la nouvelle instance PostgreSQL doit démarrer avec exactement la même clé que l'ancienne, sinon chaque credential importé sera indéchiffrable. Récupérez-la avant toute chose et fixez-la explicitement dans le compose — notre guide dédié à la N8N_ENCRYPTION_KEY détaille où la trouver et comment la conserver.

Migrer les données depuis SQLite

n8n ne convertit pas la base à chaud : la migration passe par les commandes CLI d'export/import. Sur l'ancienne instance (encore sur SQLite) :

# Export de tous les workflows (un fichier JSON par workflow)
docker exec -it n8n-old n8n export:workflow --backup --output=/home/node/.n8n/backup/workflows/

# Export de tous les credentials
docker exec -it n8n-old n8n export:credentials --backup --output=/home/node/.n8n/backup/credentials/

Le flag --backup équivaut à --all --pretty --separate. Les credentials sont exportés chiffrés : c'est très bien tant que vous réutilisez la même N8N_ENCRYPTION_KEY. Si vous ne pouvez pas la récupérer, exportez en clair avec n8n export:credentials --all --decrypted — et traitez alors ces fichiers comme des secrets (stockage temporaire, suppression après import).

Puis, sur la nouvelle instance branchée sur PostgreSQL :

docker exec -it n8n-new n8n import:workflow --separate --input=/home/node/.n8n/backup/workflows/
docker exec -it n8n-new n8n import:credentials --separate --input=/home/node/.n8n/backup/credentials/

Deux points à connaître, détaillés dans notre guide sur l'import/export de workflows n8n : les IDs sont conservés (un import écrase un workflow existant portant le même ID), et l'historique des exécutions ne migre pas — il n'existe pas de commande d'export pour les exécutions. Dans l'immense majorité des cas, ce n'est pas un problème : ce sont des données de débogage périssables, que le pruning aurait purgées de toute façon.

Vérifications post-migration

Avant de décommissionner l'ancienne instance :

  • Réactivez les workflows. Les workflows importés arrivent désactivés : réactivez-les un par un (ou via n8n update:workflow --all --active=true, puis redémarrez) en vérifiant que les webhooks se réenregistrent.
  • Testez les credentials sensibles. Ouvrez les principaux credentials et lancez une exécution de test : si la clé de chiffrement est bonne, tout se déchiffre sans intervention.
  • Confirmez la base réellement utilisée. Dans les logs de démarrage, ou en vérifiant que les tables workflow_entity et credentials_entity se remplissent côté PostgreSQL (\dt dans psql).
  • Coupez l'ancienne instance avant d'activer la nouvelle si les deux pointent vers les mêmes webhooks ou les mêmes boîtes mail : deux instances actives traiteraient chaque événement deux fois.

Maintenance PostgreSQL au quotidien

PostgreSQL ne dispense pas d'entretien, il le rend juste plus prévisible :

EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=168          # purge les exécutions de plus de 7 jours
EXECUTIONS_DATA_PRUNE_MAX_COUNT=10000

Le pruning automatique borne la croissance de la table des exécutions ; l'autovacuum de PostgreSQL récupère ensuite l'espace, là où SQLite exigeait un VACUUM manuel ou DB_SQLITE_VACUUM_ON_STARTUP. Surveillez tout de même la taille (SELECT pg_size_pretty(pg_database_size('n8n'));) et, désormais que vous êtes sur PostgreSQL, mettez en place de vraies sauvegardes à chaud — c'est l'objet de notre guide sauvegarde et restauration PostgreSQL pour n8n.

Base managée ou conteneur ?

Le conteneur postgres du compose ci-dessus convient à la plupart des instances : simple, gratuit, colocalisé (latence quasi nulle). Une base managée (RDS, Cloud SQL, Scaleway, OVH) se justifie quand vous voulez déléguer les sauvegardes, la haute disponibilité et les mises à jour de version — au prix d'un coût mensuel et d'une latence réseau à surveiller. Règle pratique : commencez par le conteneur ; passez au managé le jour où la base devient un actif que vous n'avez plus le temps d'opérer vous-même.

En résumé

SQLite est un excellent point de départ, PostgreSQL est le passage obligé dès que votre instance n8n monte en charge : concurrence d'écriture, mode queue, sauvegardes à chaud. La bascule tient en trois mouvements — les variables DB_TYPE=postgresdb et DB_POSTGRESDB_*, la conservation scrupuleuse de la N8N_ENCRYPTION_KEY, et l'export/import CLI des workflows et credentials. C'est typiquement le socle qu'exigent des workflows IA en production : le Pack Assistant RAG (119 €), avec son ingestion documentaire et ses exécutions longues, tourne d'autant plus sereinement sur une instance PostgreSQL correctement dimensionnée et prête à passer en mode queue le jour venu.

FAQ

Questions fréquentes

Peut-on migrer l'historique des exécutions de SQLite vers PostgreSQL ?

Non, pas avec les outils officiels : les commandes CLI de n8n exportent les workflows et les credentials, pas les exécutions passées. En pratique, ce n'est presque jamais bloquant : l'historique d'exécution est une donnée de débogage à durée de vie courte, que le pruning aurait de toute façon purgée en quelques semaines. Si un historique vous est légalement nécessaire, exportez-le à part (requête SQL sur la base SQLite) avant de décommissionner l'ancienne instance.

Faut-il changer la N8N_ENCRYPTION_KEY au moment de la migration ?

Non, surtout pas : conservez exactement la même clé sur la nouvelle instance. C'est elle qui déchiffre les credentials, indépendamment du moteur de base de données utilisé. Si la nouvelle instance démarre avec une autre clé, tous les credentials importés seront illisibles et il faudra soit réimporter un export --decrypted, soit tout ressaisir à la main.

SQLite est-il vraiment inutilisable en production ?

Non — pour une instance mono-conteneur avec quelques dizaines d'exécutions par jour, SQLite tient très bien et simplifie l'hébergement. Le basculement vers PostgreSQL devient nécessaire quand le volume d'exécutions grossit, que plusieurs processus doivent écrire en parallèle, ou que vous activez le mode queue avec des workers : là, SQLite n'est plus supporté.

Bundle FlowKit Complet

269 €