Por padrão, o n8n armazena dados em SQLite, um banco baseado em arquivo que não exige configuração. Ele funciona bem para testes locais, mas apresenta limitações em produção: bloqueia o arquivo durante gravações, não oferece backups seguros em tempo real e não é compatível com o modo fila (queue mode), necessário para escalar horizontalmente com workers.
O PostgreSQL resolve esses problemas e é a opção recomendada para qualquer instalação self-hosted do n8n além de uso pessoal.
Neste guia, você vai configurar o n8n com PostgreSQL usando Docker Compose e também aprender como migrar uma instância existente em SQLite de forma segura. A configuração leva cerca de 15 minutos e não exige experiência prévia com bancos de dados.
Por que migrar para PostgreSQL?
O SQLite armazena todos os dados em um único arquivo e bloqueia completamente esse arquivo a cada gravação. Quando vários workflows são executados ao mesmo tempo, as operações ficam enfileiradas e podem falhar por timeout. Em casos extremos, o arquivo pode ser corrompido. Além disso, não é possível fazer um backup consistente enquanto o n8n está em execução — copiar o arquivo durante uma gravação pode resultar em dados inconsistentes.
O PostgreSQL utiliza bloqueio em nível de linha (row-level), permitindo execuções paralelas sem conflitos. Ele suporta backups em tempo real com pg_dump, sem necessidade de interromper o n8n. Também é obrigatório para o uso do modo fila (com Redis e múltiplos workers) e para configurações com alta disponibilidade.
Se o seu n8n é usado por uma equipe ou processa mais do que algumas dezenas de workflows por dia, o PostgreSQL é a escolha mais adequada.
Pré-requisitos
- Um servidor Linux (Ubuntu 22.04 ou 24.04) com pelo menos 2 GB de RAM e 20 GB de disco;
- Docker e Docker Compose instalados;
- Acesso via SSH ao servidor;
- Para migração: acesso ao diretório de dados atual do n8n (/home/node/.n8n ou volume do Docker).
Você pode contratar uma VPS na Serverspace e deixá-la pronta em poucos minutos. Se preferir evitar a instalação manual, a Serverspace também oferece uma VPS com n8n pré-instalado como aplicação 1-Click.
Passo 1. Gerar uma chave de criptografia
O n8n criptografa todas as credenciais armazenadas usando esta chave. Se você perdê-la, todas as credenciais salvas ficarão permanentemente inacessíveis.
Gere uma chave e armazene-a em um gerenciador de senhas:
Passo 2. Criar os arquivos do projeto
Crie um diretório e adicione três arquivos dentro dele:
.env
POSTGRES_PASSWORD=your_strong_postgres_password
POSTGRES_DB=n8n
POSTGRES_NON_ROOT_USER=n8n_user
POSTGRES_NON_ROOT_PASSWORD=your_strong_n8n_password
N8N_ENCRYPTION_KEY=paste_your_generated_key_here
N8N_HOST=0.0.0.0
N8N_PROTOCOL=http
N8N_PORT=5678
GENERIC_TIMEZONE=UTC
docker-compose.yml
db_storage:
n8n_storage:
services:
postgres:
image: postgres:16-alpine
restart: always
environment:
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
- POSTGRES_NON_ROOT_USER
- POSTGRES_NON_ROOT_PASSWORD
volumes:
- db_storage:/var/lib/postgresql/data
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
interval: 5s
timeout: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
ports:
- 5678:5678
volumes:
- n8n_storage:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
O volume n8n_storage em /home/node/.n8n continua sendo necessário mesmo com PostgreSQL. O n8n ainda armazena metadados da chave de criptografia nesse diretório.
O parâmetro DB_POSTGRESDB_HOST deve corresponder ao nome do serviço no Docker Compose ("postgres"), e não "localhost".
init-data.sh
Este script cria o usuário não-root do banco de dados na primeira inicialização. Crie o arquivo e execute chmod +x init-data.sh:
#!/bin/bash
set -e;
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB"