Node.js em produção com PM2

PM2 é o gerenciador de processos mais usado para Node.js em produção, garante que a aplicação reinicia automaticamente após crashes, usa todos os CPUs disponíveis via cluster mode e centraliza logs de múltiplos processos. É a alternativa mais simples ao Docker para quem quer Node.js diretamente no host da VPS.

Instalar e iniciar a aplicação com PM2

PM2 é instalado globalmente via npm. Após instalar, inicie a aplicação e configure o startup automático:

bash
# Instalar PM2 globalmente
npm install -g pm2

# Iniciar aplicação (modo fork — 1 processo)
pm2 start dist/index.js --name "minha-api"

# Iniciar com variáveis de ambiente
pm2 start dist/index.js --name "minha-api" --env production

# Ver processos rodando
pm2 list
pm2 status

# Configurar para iniciar no boot da VPS
pm2 startup
# Executar o comando que o PM2 sugerir (ex: sudo env PATH=... pm2 startup systemd -u deploy)
pm2 save

ecosystem.config.js: configuração declarativa

O arquivo de ecosistema centraliza a configuração de todos os processos e deve ser commitado no repositório:

javascript
// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'minha-api',
      script: 'dist/index.js',
      instances: 'max',           // um processo por CPU
      exec_mode: 'cluster',       // modo cluster (workers)
      watch: false,               // nunca watch em produção
      max_memory_restart: '500M', // reiniciar se usar > 500 MB
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000,
      },
      // Logs centralizados
      out_file: '/var/log/pm2/minha-api-out.log',
      error_file: '/var/log/pm2/minha-api-err.log',
      merge_logs: true,
      log_date_format: 'YYYY-MM-DD HH:mm:ss',
      // Restart inteligente
      restart_delay: 3000,        // aguardar 3s antes de reiniciar
      max_restarts: 10,           // max 10 restarts em 15min
      min_uptime: '5s',           // mínimo 5s rodando para ser "estável"
    },
  ],
}

Cluster mode: usar todos os CPUs

No modo cluster, PM2 cria um processo por CPU e distribui requisições com balanceamento de carga nativo do Node.js:

bash
# Iniciar com ecosistema (modo cluster)
pm2 start ecosystem.config.js --env production

# Ver distribuição de carga entre workers
pm2 list
# Cada processo mostra CPU%, RAM e restarts

# Reiniciar workers um a um (zero downtime)
pm2 reload minha-api

# Escalar para número específico de instâncias
pm2 scale minha-api 4      # 4 processos
pm2 scale minha-api +2     # adicionar 2 processos
pm2 scale minha-api -1     # remover 1 processo

# Ver em que worker cada requisição está sendo processada
pm2 monit

Gerenciar logs

PM2 centraliza logs de todos os workers. Configure rotação para evitar disco cheio:

bash
# Ver logs em tempo real
pm2 logs minha-api
pm2 logs minha-api --lines 100

# Ver apenas erros
pm2 logs minha-api --err

# Limpar logs manualmente
pm2 flush minha-api

# Instalar rotação de logs automática
pm2 install pm2-logrotate

# Configurar rotação
pm2 set pm2-logrotate:max_size 10M    # arquivo máximo 10 MB
pm2 set pm2-logrotate:retain 7        # manter 7 arquivos rotacionados
pm2 set pm2-logrotate:compress true   # comprimir arquivos antigos

Deploy com PM2 (sem Docker)

Script de deploy para aplicações Node.js gerenciadas pelo PM2 diretamente no host:

bash
#!/bin/bash
# deploy.sh

VPS_USER=deploy
VPS_HOST=IP_DA_VPS
APP_DIR=/opt/minha-api

# Sincronizar arquivos
rsync -avz --exclude='node_modules' --exclude='.env' --exclude='.git' \
  ./ $VPS_USER@$VPS_HOST:$APP_DIR/

# Na VPS: instalar deps, build e reload
ssh $VPS_USER@$VPS_HOST "
  cd $APP_DIR
  npm ci --only=production
  npm run build
  pm2 reload ecosystem.config.js --env production
  pm2 save
"

Não quer configurar manualmente?

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

Perguntas frequentes

PM2 cluster mode usa o módulo cluster do Node.js, cria processos separados (cada um com sua própria memória e event loop). worker_threads usa threads dentro do mesmo processo, compartilham memória via SharedArrayBuffer. Para escalabilidade horizontal de I/O-bound apps (APIs): PM2 cluster. Para CPU-bound (cálculos pesados em paralelo): worker_threads.

Sim. Em cluster mode, cada worker é um processo separado, uma conexão WebSocket estabelecida com o worker 1 não existe para o worker 2. Solução: use sticky sessions no load balancer (Nginx: ip_hash) ou externalize o estado para Redis (sessões, pub/sub para WebSocket com socket.io-redis).

pm2 monit mostra CPU, RAM e logs em tempo real no terminal. Para dashboards web: pm2 plus (pago) ou exponha métricas via @pm2/io e visualize no Grafana. Para alertas básicos: configure pm2-health-check ou use o webhook do PM2 para Slack/n8n.

Systemd: nativo no Linux, zero dependência extra, excelente integração com journald (logs). PM2: específico para Node.js, cluster mode, deploy com zero downtime, interface mais amigável. Para projetos simples com um processo: systemd é mais leve. Para múltiplas apps Node.js com scaling: PM2 é mais conveniente.

Opção 1: arquivo .env na raiz do projeto + dotenv no código (não commitado). Opção 2: env_production no ecosystem.config.js (cuidado para não commitar segredos). Opção 3: definir no sistema antes de iniciar o PM2: export CHAVE=valor && pm2 start. Nunca coloque API keys ou senhas diretamente no ecosystem.config.js commitado.