Pular para o conteúdo principal

Otimização de Performance

Este documento detalha como otimizar performance do n8n para máxima eficiência, incluindo configuração de workers, ajuste de timeouts, otimização de queries de banco, gerenciamento de memória, monitoramento de recursos, e técnicas avançadas de tuning que maximizam throughput e minimizam latência em workflows de alta demanda para operações empresariais críticas.


Configuração de Workers

Docker Compose Otimizado

version: '3.8'

services:
  # Worker principal
  n8n-main:
    image: n8nio/n8n:latest
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - EXECUTIONS_PROCESS=main
      - EXECUTIONS_MODE=regular
      - REDIS_URL=redis://redis:6379
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - EXECUTIONS_TIMEOUT=300000
      - EXECUTIONS_TIMEOUT_MAX=3600000
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '1.0'
        reservations:
          memory: 1G
          cpus: '0.5'
    depends_on:
      - postgres
      - redis
    networks:
      - n8n_network

  # Workers de execução otimizados
  n8n-worker-1:
    image: n8nio/n8n:latest
    restart: unless-stopped
    environment:
      - EXECUTIONS_PROCESS=worker
      - EXECUTIONS_MODE=regular
      - REDIS_URL=redis://redis:6379
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - EXECUTIONS_TIMEOUT=300000
      - EXECUTIONS_TIMEOUT_MAX=3600000
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '1.0'
        reservations:
          memory: 1G
          cpus: '0.5'
    depends_on:
      - postgres
      - redis
    networks:
      - n8n_network

  n8n-worker-2:
    image: n8nio/n8n:latest
    restart: unless-stopped
    environment:
      - EXECUTIONS_PROCESS=worker
      - EXECUTIONS_MODE=regular
      - REDIS_URL=redis://redis:6379
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - EXECUTIONS_TIMEOUT=300000
      - EXECUTIONS_TIMEOUT_MAX=3600000
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '1.0'
        reservations:
          memory: 1G
          cpus: '0.5'
    depends_on:
      - postgres
      - redis
    networks:
      - n8n_network

  # Banco de dados otimizado
  postgres:
    image: postgres:15
    restart: unless-stopped
    environment:
      - POSTGRES_DB=n8n
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./postgresql.conf:/etc/postgresql/postgresql.conf
    command: postgres -c config_file=/etc/postgresql/postgresql.conf
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: '2.0'
        reservations:
          memory: 2G
          cpus: '1.0'
    networks:
      - n8n_network

  # Redis otimizado
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --appendonly yes --maxmemory 1gb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: '0.5'
        reservations:
          memory: 512M
          cpus: '0.25'
    networks:
      - n8n_network

volumes:
  postgres_data:
  redis_data:

networks:
  n8n_network:
    driver: bridge

Otimização de Timeouts

Configuração de Timeouts

# Timeouts por tipo de operação
EXECUTIONS_TIMEOUT=300000          # 5 minutos para execuções normais
EXECUTIONS_TIMEOUT_MAX=3600000     # 1 hora para execuções longas
WEBHOOK_TIMEOUT=120000             # 2 minutos para webhooks
API_TIMEOUT=60000                  # 1 minuto para APIs

Otimização de Banco de Dados

PostgreSQL Otimizado

# postgresql.conf - Otimizações
# Logs
log_destination = 'stderr'
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d
log_rotation_size = 100MB
log_min_duration_statement = 1000  # Log queries > 1s

# Performance
shared_buffers = 256MB
effective_cache_size = 1GB
work_mem = 4MB
maintenance_work_mem = 64MB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200

# Connections
max_connections = 100

Script de Manutenção

#!/bin/bash

# Configurações
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="n8n"
DB_USER="n8n"

echo "=== Manutenção do Banco de Dados ==="
echo

echo "1. Executando VACUUM e ANALYZE..."
psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -c "VACUUM ANALYZE;"
echo

echo "2. Reindexando tabelas..."
psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -c "REINDEX DATABASE $DB_NAME;"
echo

echo "3. Atualizando estatísticas..."
psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -c "ANALYZE;"
echo

echo "4. Limpando execuções antigas..."
psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -c "
DELETE FROM executions
WHERE created_at < NOW() - INTERVAL '30 days'
AND status IN ('success', 'error');"
echo

echo "Manutenção concluída!"

Otimização de Memória

Configuração Node.js

# Variáveis de ambiente para otimização de memória
NODE_OPTIONS="--max-old-space-size=4096 --max-semi-space-size=512"

# Docker com otimizações de memória
docker run -e NODE_OPTIONS="--max-old-space-size=4096" n8nio/n8n

Configuração de Memória Redis

# redis.conf - Otimizações de memória
maxmemory 1gb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
save 60 10000

Monitoramento de Memória

#!/bin/bash

echo "=== Monitoramento de Memória ==="
echo

echo "1. Memória do Sistema:"
free -h
echo

echo "2. Memória dos Containers:"
docker stats --no-stream --format "table {{.Container}}\t{{.MemUsage}}\t{{.MemPerc}}"
echo

echo "3. Memória do Node.js:"
for container in n8n-main n8n-worker-1 n8n-worker-2; do
    echo "=== $container ==="
    docker exec $container node -e "
        const mem = process.memoryUsage();
        console.log('RSS:', Math.round(mem.rss / 1024 / 1024) + 'MB');
        console.log('Heap Used:', Math.round(mem.heapUsed / 1024 / 1024) + 'MB');
        console.log('Heap Total:', Math.round(mem.heapTotal / 1024 / 1024) + 'MB');
    "
done
echo

echo "4. Memória Redis:"
redis-cli info memory | grep -E "(used_memory_human|maxmemory_human)"
echo

echo "5. Alertas de Memória:"
MEMORY_THRESHOLD=85
for container in n8n-main n8n-worker-1 n8n-worker-2; do
    MEMORY_PERC=$(docker stats --no-stream --format "{{.MemPerc}}" $container | sed 's/%//')
    if (( $(echo "$MEMORY_PERC > $MEMORY_THRESHOLD" | bc -l) )); then
        echo "⚠️ ALERTA: $container usando $MEMORY_PERC% de memória"
    fi
done

Monitoramento de Performance

Métricas de Performance

#!/bin/bash

echo "=== Métricas de Performance ==="
echo

echo "1. Uso de Recursos:"
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"
echo

echo "2. Execuções por Minuto:"
EXECUTIONS_PER_MIN=$(psql -h localhost -U n8n -d n8n -t -c "
SELECT COUNT(*) FROM executions
WHERE created_at > NOW() - INTERVAL '1 minute';")
echo "Execuções no último minuto: $EXECUTIONS_PER_MIN"
echo

echo "3. Tempo Médio de Execução:"
AVG_EXECUTION_TIME=$(psql -h localhost -U n8n -d n8n -t -c "
SELECT AVG(EXTRACT(EPOCH FROM (finished_at - started_at)))
FROM executions
WHERE finished_at IS NOT NULL
AND created_at > NOW() - INTERVAL '1 hour';")
echo "Tempo médio (última hora): ${AVG_EXECUTION_TIME}s"
echo

echo "4. Taxa de Erro:"
ERROR_RATE=$(psql -h localhost -U n8n -d n8n -t -c "
SELECT
    ROUND(
        (COUNT(CASE WHEN status = 'error' THEN 1 END) * 100.0 / COUNT(*)), 2
    ) as error_rate
FROM executions
WHERE created_at > NOW() - INTERVAL '1 hour';")
echo "Taxa de erro (última hora): ${ERROR_RATE}%"
echo

echo "5. Status das Filas:"
echo "Jobs na fila: $(redis-cli llen n8n:queue:jobs)"
echo "Webhooks na fila: $(redis-cli llen n8n:queue:webhooks)"
echo "Jobs processados: $(redis-cli get n8n:stats:processed || echo '0')"
echo "Jobs falharam: $(redis-cli get n8n:stats:failed || echo '0')"

Alertas de Performance

#!/bin/bash

# Configurações
CPU_THRESHOLD=80
MEMORY_THRESHOLD=85
ERROR_RATE_THRESHOLD=10
EXECUTION_TIME_THRESHOLD=300
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

# Verificar CPU
for container in n8n-main n8n-worker-1 n8n-worker-2; do
    CPU_USAGE=$(docker stats --no-stream --format "{{.CPUPerc}}" $container | sed 's/%//')
    if (( $(echo "$CPU_USAGE > $CPU_THRESHOLD" | bc -l) )); then
        curl -X POST $WEBHOOK_URL \
          -H "Content-type: application/json" \
          -d "{\"text\":\"⚠️ CPU alta em $container: ${CPU_USAGE}%\"}"
    fi
done

# Verificar memória
for container in n8n-main n8n-worker-1 n8n-worker-2; do
    MEMORY_USAGE=$(docker stats --no-stream --format "{{.MemPerc}}" $container | sed 's/%//')
    if (( $(echo "$MEMORY_USAGE > $MEMORY_THRESHOLD" | bc -l) )); then
        curl -X POST $WEBHOOK_URL \
          -H "Content-type: application/json" \
          -d "{\"text\":\"⚠️ Memória alta em $container: ${MEMORY_USAGE}%\"}"
    fi
done

# Verificar taxa de erro
ERROR_RATE=$(psql -h localhost -U n8n -d n8n -t -c "
SELECT ROUND((COUNT(CASE WHEN status = 'error' THEN 1 END) * 100.0 / COUNT(*)), 2)
FROM executions 
WHERE created_at > NOW() - INTERVAL '10 minutes';" | xargs)

if (( $(echo "$ERROR_RATE > $ERROR_RATE_THRESHOLD" | bc -l) )); then
    curl -X POST $WEBHOOK_URL \
      -H "Content-type: application/json" \
      -d "{\"text\":\"🚨 Taxa de erro alta: ${ERROR_RATE}%\"}"
fi

# Verificar tempo de execução
AVG_TIME=$(psql -h localhost -U n8n -d n8n -t -c "
SELECT AVG(EXTRACT(EPOCH FROM (finished_at - started_at)))
FROM executions 
WHERE finished_at IS NOT NULL 
AND created_at > NOW() - INTERVAL '10 minutes';" | xargs)

if (( $(echo "$AVG_TIME > $EXECUTION_TIME_THRESHOLD" | bc -l) )); then
    curl -X POST $WEBHOOK_URL \
      -H "Content-type: application/json" \
      -d "{\"text\":\"🐌 Tempo de execução alto: ${AVG_TIME}s\"}"
fi

Técnicas Avançadas de Tuning

Otimização de Workflows

// 1. Usar batch processing para grandes volumes
const batchSize = 100;
const items = await getItems();
for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    await processBatch(batch);
}

// 2. Implementar cache para dados frequentes
const cache = new Map();
async function getCachedData(key) {
    if (cache.has(key)) {
        return cache.get(key);
    }
    
    const data = await fetchData(key);
    cache.set(key, data);
    return data;
}

// 3. Usar paralelismo quando possível
const promises = items.map(item => processItem(item));
const results = await Promise.all(promises);

// 4. Implementar retry com backoff exponencial
async function retryWithBackoff(fn, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
        try {
            return await fn();
        } catch (error) {
            if (i === maxRetries - 1) throw error;
            await new Promise(resolve =>
                setTimeout(resolve, Math.pow(2, i) * 1000)
            );
        }
    }
}

Otimização de Rede

# Otimizações de rede para Linux
# /etc/sysctl.conf
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

Troubleshooting de Performance

#!/bin/bash

echo "=== Diagnóstico de Performance ==="
echo

echo "1. Logs de performance:"
docker logs n8n-main | grep -E "(slow|timeout|error)"
echo

echo "2. Queries lentas do banco:"
psql -h localhost -U n8n -d n8n -c "
SELECT query, mean_time, calls
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;"
echo

echo "3. Memory leaks:"
for container in n8n-main n8n-worker-1 n8n-worker-2; do
    echo "=== $container ==="
    docker exec $container node -e "
        const mem = process.memoryUsage();
        console.log('RSS:', Math.round(mem.rss / 1024 / 1024) + 'MB');
        console.log('Heap Used:', Math.round(mem.heapUsed / 1024 / 1024) + 'MB');
    "
done
echo

echo "4. GC analysis:"
docker exec n8n-main node --trace-gc -e "console.log('GC test')"

Problemas Comuns

#!/bin/bash

echo "=== Problemas Comuns de Performance ==="
echo

echo "1. Timeouts frequentes:"
docker exec n8n-main env | grep -E "(TIMEOUT|EXECUTIONS)"
echo

echo "2. Memory leaks:"
docker stats --no-stream --format "table {{.Container}}\t{{.MemUsage}}\t{{.MemPerc}}"
echo

echo "3. CPU spikes:"
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}"
echo

echo "4. Network issues:"
netstat -i
echo

echo "5. Disk I/O:"
iostat -x 1 3

Checklist de Otimização

Configuração

  • Workers configurados adequadamente
  • Timeouts otimizados
  • Memória alocada corretamente
  • Redis configurado para performance
  • Banco de dados otimizado

Monitoramento

  • Métricas de performance configuradas
  • Alertas configurados
  • Logs estruturados
  • Dashboard de monitoramento
  • Health checks implementados

Otimização

  • Queries de banco otimizadas
  • Cache implementado
  • Batch processing configurado
  • Paralelismo utilizado
  • Retry policies definidas

Manutenção

  • Limpeza automática de dados antigos
  • Backup configurado
  • Log rotation ativado
  • Monitoramento de recursos
  • Alertas de performance

Dica Pro

Monitore constantemente as métricas de performance e ajuste as configurações conforme necessário. Use ferramentas como Prometheus e Grafana para visualização avançada.

Importante

Sempre teste otimizações de performance em ambiente de desenvolvimento antes de aplicar em produção. Monitore o impacto das mudanças.