Migrar SQLite para PostgreSQL

SQLite é o banco padrão de muitas ferramentas self-hosted (n8n, Flowise, NocoDB) por ser simples de configurar, mas não escala bem com múltiplos usuários simultâneos. A migração para PostgreSQL é necessária quando o app começa a travar, o banco de dados fica corrupto após crash, ou você precisa de backup consistente. O processo preserva todos os dados e não requer reinstalação do app.

Quando migrar de SQLite para PostgreSQL

SQLite tem limitações claras que indicam quando a migração é necessária:

bash
# Sinais de que o SQLite está sendo o gargalo:

# 1. Erros "database is locked" nos logs
docker compose logs nome_do_app | grep -i "locked\|busy\|database"

# 2. Múltiplos usuários ou workers acessando simultaneamente
# SQLite suporta apenas um escritor por vez

# 3. Banco > 1 GB (performance degrada)
ls -lh caminho/para/o/banco.sqlite

# 4. Necessidade de backup consistente (pg_dump vs cp do arquivo)

# 5. App rodando com múltiplos réplicas ou workers
# SQLite em bind mount compartilhado entre containers = corrupção certa

# Verificar tamanho e último acesso ao banco SQLite
docker compose exec nome_app find / -name "*.sqlite" -o -name "*.db" 2>/dev/null

Migrar n8n de SQLite para PostgreSQL

n8n armazena workflows, credenciais e execuções no banco. A migração oficial usa variáveis de ambiente, não existe comando de migração automática, mas os dados não precisam ser migrados (workflows são re-importados):

yaml
# Opção 1: Exportar workflows e recriar do zero (mais simples)
# 1. Exportar todos os workflows via interface n8n
#    Settings → Import/Export → Export all workflows

# 2. Adicionar PostgreSQL ao docker-compose.yml
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pg_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n"]
      interval: 5s
      retries: 5

  n8n:
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_DATABASE: n8n
      DB_POSTGRESDB_USER: n8n
      DB_POSTGRESDB_PASSWORD: ${DB_PASSWORD}
    depends_on:
      postgres:
        condition: service_healthy

# 3. Recriar containers (banco vazio, migração automática na 1ª inicialização)
docker compose down
docker compose up -d

# 4. Importar workflows exportados
#    Settings → Import/Export → Import from file

Migrar banco SQLite genérico com pgloader

pgloader converte automaticamente tipos de dados e migra os dados de SQLite para PostgreSQL:

bash
# Copiar o arquivo SQLite do container para o host
docker cp nome_do_container:/caminho/para/banco.sqlite ./banco.sqlite

# Criar banco de destino no PostgreSQL
docker compose exec postgres psql -U postgres \
  -c "CREATE DATABASE nome_do_banco OWNER postgres;"

# Rodar pgloader
docker run --rm \
  --network nome_da_rede_docker \
  -v $(pwd)/banco.sqlite:/tmp/banco.sqlite \
  dimitri/pgloader:latest pgloader \
  /tmp/banco.sqlite \
  postgresql://postgres:senha@postgres/nome_do_banco

# Verificar contagem de registros após migração
docker compose exec postgres psql -U postgres -d nome_do_banco \
  -c "SELECT tablename, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC;"

Migrar Flowise de SQLite para PostgreSQL

Flowise suporta PostgreSQL via variável de ambiente, a migração é transparente após configurar o banco:

bash
# No docker-compose.yml do Flowise, adicionar/alterar:
services:
  flowise:
    environment:
      DATABASE_TYPE: postgres
      DATABASE_HOST: postgres
      DATABASE_PORT: 5432
      DATABASE_NAME: flowise
      DATABASE_USER: flowise
      DATABASE_PASSWORD: ${DB_PASSWORD}

# Primeiro, criar o banco no PostgreSQL:
docker compose exec postgres psql -U postgres << 'EOF'
CREATE USER flowise WITH PASSWORD 'sua_senha';
CREATE DATABASE flowise OWNER flowise;
GRANT ALL PRIVILEGES ON DATABASE flowise TO flowise;
EOF

# Recriar o container do Flowise
docker compose down flowise
docker compose up -d flowise

# Na primeira inicialização, Flowise cria o schema automaticamente
docker compose logs flowise --tail=20

Verificar a migração e rollback

Valide os dados antes de remover o SQLite e saiba como fazer rollback se necessário:

bash
# Comparar contagem de registros SQLite vs PostgreSQL
# SQLite (via sqlite3 local ou dentro do container):
docker compose exec nome_app sqlite3 /caminho/banco.sqlite \
  "SELECT name, COUNT(*) FROM sqlite_master WHERE type='table' GROUP BY name;"

# PostgreSQL:
docker compose exec postgres psql -U postgres -d nome_do_banco \
  -c "SELECT tablename, n_live_tup FROM pg_stat_user_tables;"

# Manter backup do SQLite por 30 dias antes de deletar
cp banco.sqlite banco-sqlite-backup-$(date +%Y%m%d).sqlite

# Rollback: reverter variáveis de ambiente e apontar para SQLite novamente
# Dados criados após a migração serão perdidos no rollback

Não quer configurar manualmente?

Implante o PostgreSQL em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Depende do volume. SQLite aguenta bem apps com < 10 usuários simultâneos e < 100 writes/segundo. O problema aparece com: múltiplos workers acessando o mesmo arquivo (corrupção), backup durante uso (arquivo inconsistente), e deploys com zero downtime (impossível com SQLite em arquivo local).

O n8n suporta SQLite em produção para uso individual ou equipe pequena (< 5 usuários). Para escalar com múltiplos workers (queue mode) ou alta frequência de execuções, PostgreSQL é obrigatório, o n8n não suporta queue mode com SQLite.

Sim. pgloader é o melhor utilitário de migração entre bancos: suporta MySQL, MariaDB, SQLite e MS SQL → PostgreSQL. Converte tipos de dados, reescreve sequências e handles de auto_increment. Para MySQL: pgloader mysql://usuario:senha@host/banco postgresql://...

Provavelmente falta de índices ou queries não otimizadas que eram toleráveis no SQLite (banco local sem overhead de rede) mas lentas no PostgreSQL (banco remoto via TCP). Ative pg_stat_statements e identifique as queries mais lentas. Na maioria dos casos, um índice resolve.

Infelizmente não há migração automática oficial para execuções e credenciais. Workflows podem ser exportados/importados via UI. Credenciais precisam ser reconfiguradas. Histórico de execuções não é migrado, mas fica acessível no banco SQLite antigo para consulta. Para preservar o histórico, considere usar pgloader para migrar as tabelas de execuções manualmente.