PM2 em produção com Node.js ajuda a iniciar, reiniciar e observar processos JavaScript em servidores tradicionais. Ele oferece gerenciamento de logs, modo cluster, reinício por memória, variáveis por ambiente e integração com o sistema de inicialização. É útil quando a aplicação roda diretamente em uma máquina virtual ou servidor dedicado, sem um orquestrador de contêineres responsável pelo ciclo de vida.
PM2 não substitui arquitetura, health checks, backups ou monitoramento externo. Um processo que reinicia continuamente continua com defeito. Neste guia, você aprenderá a configurar o gerenciador com limites, shutdown correto e deploy previsível. Para revisar a plataforma, leia o que é Node.js e graceful shutdown no Node.js.
Quando usar PM2?
Use PM2 quando administra processos em Linux e deseja recursos de supervisão sem montar um serviço systemd manual para cada aplicação. Em Kubernetes, ECS ou plataformas PaaS, o orquestrador normalmente já controla restart, réplicas e logs; adicionar PM2 pode criar duas camadas competindo pelo mesmo processo.
Antes de escolher, defina quem é responsável por iniciar, reiniciar, escalar e encerrar. Uma única camada de supervisão torna o comportamento mais previsível.
Instalação
npm install --global pm2
pm installFixe a versão usada no processo de deploy e documente a atualização. A instalação global facilita comandos administrativos, mas o pipeline precisa reproduzir a mesma versão entre ambientes.
Arquivo ecosystem
Centralize a configuração em um arquivo versionado. Não grave segredos nele; use variáveis injetadas pelo ambiente ou um gerenciador apropriado.
module.exports = {
apps: [{
name: 'orders-api',
script: './dist/server.js',
instances: 'max',
exec_mode: 'cluster',
autorestart: true,
watch: false,
max_memory_restart: '500M',
kill_timeout: 15000,
listen_timeout: 10000,
wait_ready: true,
exp_backoff_restart_delay: 100,
env: {
NODE_ENV: 'production',
PORT: 3000
}
}]
};wait_ready exige que a aplicação envie um sinal quando estiver pronta. kill_timeout define quanto tempo o PM2 aguarda antes de forçar encerramento. Ajuste esses valores ao tempo real de inicialização e shutdown.
Sinalizando readiness
const server = app.listen(process.env.PORT, () => {
if (process.send) {
process.send('ready');
}
});Envie ready somente depois que configurações obrigatórias foram validadas e recursos essenciais estão disponíveis. Se o banco estiver indisponível, decida se a aplicação deve falhar ao iniciar ou ficar viva, porém não pronta. O guia de health checks no Node.js explica liveness e readiness.
Modo cluster
O cluster inicia múltiplos processos compartilhando a mesma porta. Ele aproveita vários núcleos e distribui conexões. Cada worker possui memória, cache e event loop independentes. Portanto, sessão, rate limiting e estado de negócio não devem depender da memória de um único processo.
Use Redis, banco ou outro armazenamento compartilhado quando a informação precisa ser consistente entre workers. Caches locais podem existir, mas precisam tolerar divergência e invalidação.
Quantidade de instâncias
instances: 'max' usa os CPUs disponíveis, mas isso nem sempre é ideal. Um servidor também precisa de memória, sistema operacional, proxy e banco local. Comece com um valor medido e acompanhe latência, CPU, memória e saturação de dependências.
Mais workers podem aumentar conexões com o banco. Ajuste pools por processo para que a soma não ultrapasse a capacidade do servidor. Consulte pool PostgreSQL no Node.js.
Graceful shutdown
PM2 envia sinais durante reload e stop. A aplicação deve parar de aceitar novas conexões, concluir requisições em andamento e fechar pools, filas e clientes.
let shuttingDown = false;
async function shutdown(signal) {
if (shuttingDown) return;
shuttingDown = true;
logger.info({ signal }, 'shutdown_started');
server.close(async error => {
await Promise.allSettled([
database.close(),
queue.close()
]);
process.exit(error ? 1 : 0);
});
setTimeout(() => process.exit(1), 14000).unref();
}
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));O prazo interno deve ser menor que kill_timeout, permitindo que a aplicação registre e encerre antes do sinal forçado.
Reload sem indisponibilidade
pm2 reload substitui workers gradualmente no modo cluster. O benefício depende de readiness e shutdown corretos. Se o processo sinaliza pronto cedo demais ou mantém conexões indefinidamente, o reload pode causar erros.
pm2 start ecosystem.config.cjs
pm2 reload orders-api
pm2 statusExecute migrations separadamente e antes do reload. Mudanças de banco precisam ser compatíveis com a versão antiga e a nova durante a transição.
Reinício com backoff
Uma falha permanente pode criar um loop rápido de restart, consumindo CPU e enchendo logs. exp_backoff_restart_delay aumenta o intervalo entre tentativas. Ainda assim, configure alertas para processos instáveis e corrija a causa.
Não use restart como tratamento normal de exceções. Erros previstos devem ser tratados dentro da aplicação; bugs críticos podem encerrar o processo para que a supervisão faça uma recuperação limpa.
Limite de memória
max_memory_restart protege o servidor de crescimento descontrolado, mas não corrige vazamentos. Monitore heap, RSS, taxa de garbage collection e quantidade de reinícios. Use o módulo V8 no Node.js para diagnóstico de memória.
Defina o limite abaixo da capacidade total, considerando todos os workers. Reinícios frequentes por memória são um incidente, não uma estratégia de operação.
Logs
PM2 captura stdout e stderr. Em produção, prefira logs estruturados em JSON e envie-os a um coletor externo. Configure rotação para que o disco não encha. Não misture logs de aplicação com dados sensíveis.
pm2 logs orders-api --lines 200
pm2 describe orders-api
pm2 monitEsses comandos ajudam no diagnóstico local, mas métricas e alertas devem existir fora da máquina. Se o servidor cair, o histórico local também pode ficar indisponível.
Inicialização com o sistema
Use pm2 startup para gerar a integração com systemd e pm2 save para persistir a lista de processos. Revise cuidadosamente o comando gerado e execute com o usuário correto.
pm2 startup
pm2 save
systemctl status pm2-appuserNão execute aplicações como root. Crie um usuário de serviço com acesso apenas aos diretórios e recursos necessários.
Estrutura de deploy
Um deploy seguro cria um artefato imutável, instala dependências com lockfile, executa testes, publica em um diretório versionado e troca um link simbólico. Depois, roda migrations compatíveis e faz reload. Mantenha a versão anterior para rollback rápido.
O artigo sobre deploy com GitHub Actions mostra como automatizar verificações.
Segurança
- execute PM2 e a aplicação com usuário sem privilégio;
- proteja arquivos de configuração e logs;
- injete segredos por serviço seguro;
- mantenha Node.js e PM2 atualizados;
- restrinja acesso SSH;
- não exponha dashboards administrativos publicamente;
- use proxy reverso com TLS;
- audite comandos de deploy.
Testes operacionais
Além dos testes de código, valide o ciclo de vida:
- início com dependência saudável;
- falha de configuração;
- reload com tráfego contínuo;
- SIGTERM durante uma requisição lenta;
- worker que excede memória;
- reinício da máquina;
- rollback para versão anterior;
- indisponibilidade do banco.
Use um teste de carga moderado durante reload e confirme que não há picos de erro. Os princípios de testes unitários com Jest continuam importantes para as regras internas.
Observabilidade
Monitore workers online, reinícios, uptime, CPU, RSS, heap, event loop, latência, status HTTP e conexões com dependências. Correlacione reinícios com deploys e picos de tráfego. Um worker constantemente mais carregado pode indicar sessões persistentes, conexões longas ou distribuição desigual.
Erros comuns
- Usar watch em produção: mudanças e arquivos temporários provocam reinícios;
- Guardar sessão em memória: usuários alternam entre workers;
- Pool grande por worker: o banco recebe conexões demais;
- Sem shutdown: reload interrompe requisições;
- Executar como root: aumenta o impacto de uma falha;
- Confiar apenas em restart: defeitos permanentes ficam ocultos por algum tempo.
Checklist
- ecosystem está versionado;
- segredos ficam fora do arquivo;
- readiness usa wait_ready;
- shutdown termina antes do kill_timeout;
- instâncias e pools foram medidos;
- logs possuem rotação e coleta externa;
- startup e reboot foram testados;
- rollback está documentado.
Referências oficiais
Conclusão
PM2 em produção com Node.js é uma solução prática para supervisionar processos em servidores tradicionais. Modo cluster, reload, backoff e limite de memória ajudam, desde que a aplicação seja stateless, sinalize readiness e encerre recursos corretamente.
Trate o PM2 como parte de uma operação maior: artefatos imutáveis, monitoramento externo, logs centralizados, usuário restrito e rollback. Assim, o gerenciador não apenas reinicia processos, mas participa de um ciclo de vida previsível e verificável.




