'server reached pm.max_children' na loja virtual: como dimensionar os processos PHP-FPM pela memória da VPS antes de concluir que falta servidor

Aprenda a calcular o pm.max_children certo para sua VPS. Meça o consumo de cada processo PHP-FPM, desconte banco e cache, e evite fila com a máquina ociosa.

2026-09-23 · Equipe · 10 min de leitura

A linha ‘server reached pm.max_children’ no log quer dizer que todos os processos PHP da loja estão ocupados e os próximos clientes estão na fila. Antes de comprar servidor, faça a conta de quantos processos cabem na memória da VPS: meça quanto cada um consome, desconte banco, cache e sistema, e divida o que sobra.

Quando o log do PHP-FPM mostra ‘server reached pm.max_children’, a loja não ficou necessariamente sem servidor: ficou sem processo livre para executar o PHP. Antes de trocar de máquina, confira se o limite foi calculado pela memória da VPS: meça o consumo de cada processo, desconte banco, cache e sistema, e divida o que sobra.

  • ‘server reached pm.max_children’ significa que todos os processos PHP-FPM estão ocupados. As próximas requisições esperam na fila e, se a espera fica longa, o visitante recebe 502 ou 504.
  • O limite certo é a memória que sobra depois de sistema, banco e cache, dividida pelo consumo real de cada processo.
  • Limite baixo trava a loja com a máquina ociosa. Limite alto leva ao swap e ao OOM killer, queda pior que a fila.
  • Se o processo está parado esperando frete, gateway ou banco, subir o limite não resolve.
  • Se o limite já está calculado e a memória acabou, falta máquina. Aí entra o burst: cada servidor extra chega com a própria cota de processos.

Loja parada com a CPU tranquila e ‘server reached pm.max_children’ no log

No pico, a loja trava ou devolve 502 e 504, a CPU está folgada e o log do PHP-FPM registra WARNING: [pool www] server reached pm.max_children setting. O PHP-FPM chegou ao teto de processos e todos estão ocupados: acabou atendente livre, não processador.

Onde fica o log: no Debian e no Ubuntu, /var/log/php8.2-fpm.log (troque 8.2 pela sua versão); na família Red Hat, /var/log/php-fpm/error.log; em contêiner, docker logs.

Para contar as ocorrências por dia e hora: grep max_children /var/log/php8.2-fpm.log | cut -c2-15 | sort | uniq -c. Se elas se concentram no horário de campanha, o limite trava a loja quando ela mais vende. Os códigos de erro estão em o que 502, 503 e 504 significam.

PHP-FPM como fila de atendentes: pm.max_children, pm e pm.max_requests

O PHP-FPM (FastCGI Process Manager) mantém processos prontos para executar o PHP da loja, seja WooCommerce, Magento ou outra plataforma. O nginx ou o Apache repassa cada visita a um desses processos, que atende uma requisição por vez, como um guichê com um atendente só.

  • pm.max_children: o máximo de atendentes simultâneos. Com todos ocupados, a requisição espera na fila até virar 504 (tempo do nginx esgotado) ou 502 (fila transbordada).
  • pm (process manager): a regra que decide quando abrir e fechar processos.
  • pm.max_requests: quantas requisições um processo atende antes de ser reciclado. Protege contra plugin com vazamento de memória.

static, dynamic e ondemand

  • static mantém sempre o máximo de processos abertos. Serve para VPS dedicada à loja.
  • dynamic mantém uma faixa entre mínimo e máximo, ajustada por pm.start_servers, pm.min_spare_servers e pm.max_spare_servers.
  • ondemand abre processo quando chega requisição e o fecha após um tempo parado. Serve para pouco tráfego ou vários sites na mesma máquina.

Os três obedecem ao mesmo teto, pm.max_children: trocar de modo muda quando os processos abrem, não a capacidade.

Como medir a memória real de cada processo PHP-FPM com ps e smem

Meça com a loja em movimento, no pico ou num teste de carga. Processo ocioso consome menos e distorce a conta.

ps -eo pid,rss,cmd | grep '[p]hp-fpm: pool' lista os processos que atendem cliente, sem o mestre e sem a linha do grep. RSS é a memória física ocupada, em kilobytes.

Média em megabytes: ps -eo rss,cmd | grep '[p]hp-fpm: pool' | awk '{s+=$1; n++} END {print s/n/1024}'. O RSS superestima o consumo, porque a memória compartilhada (o código do PHP e o OPcache, que guarda o código já compilado) aparece repetida em cada processo.

O smem mostra a coluna PSS, que divide a memória compartilhada entre os processos e é mais fiel. Não vem instalado: no Debian e no Ubuntu, apt install smem; depois, smem -k -t -P '^php-fpm: pool'.

Use a média com margem para os processos pesados: admin, importação e relatório gastam mais que página de produto. Em contêiner, docker stats mostra o total; dividido pelo número de processos, dá uma estimativa.

O memory_limit do php.ini é o teto de um único script, não o consumo típico. Dividir a memória por ele dá o pior caso, não a média.

A conta de quantos processos PHP-FPM cabem na memória da VPS

(memória total − sistema operacional − banco de dados − cache − margem de segurança) ÷ memória média por processo = pm.max_children

O free -m mostra o total. Para MySQL, Redis ou Memcached, use ps ou smem filtrando pelo nome. O buffer do InnoDB (innodb_buffer_pool_size) tende a ser ocupado por inteiro: conte o valor configurado, não o consumo atual.

Exemplo de cálculo (ilustração)

Números inventados para mostrar a mecânica, não medida de nenhuma loja.

  1. VPS hipotética com 8.000 MB.
  2. Menos 1.000 MB do sistema: sobram 7.000 MB.
  3. Menos 2.000 MB do buffer do MySQL e 500 MB do Redis: sobram 4.500 MB.
  4. Menos 1.000 MB de margem: sobram 3.500 MB.
  5. Dividindo por 80 MB de média por processo, dá 43,75. Arredonde para baixo: o limite fica em 43.

O arquivo do pool costuma ser /etc/php/8.2/fpm/pool.d/www.conf no Debian e no Ubuntu, e /etc/php-fpm.d/www.conf na família Red Hat. Depois de alterar, recarregue com systemctl reload php8.2-fpm (ou php-fpm na Red Hat). Com pm = dynamic, mantenha start, min e max spare servers dentro do novo teto.

Os dois erros opostos: limite baixo trava a loja ociosa, limite alto leva ao swap e ao OOM killer

Limite baixo. O aviso aparece com a máquina folgada. É comum quando o www.conf padrão, que vem com pm.max_children = 5, nunca foi ajustado ao tamanho da VPS.

Limite alto. O PHP-FPM abre mais processos do que a memória comporta e o sistema passa a usar o swap, área do disco que faz papel de memória quando a RAM acaba. Como o disco é muito mais lento, a loja inteira responde devagar, inclusive o banco.

Quando a memória acaba de vez, o OOM killer (Out Of Memory killer) do Linux mata processos para liberá-la. Costuma escolher o maior, muitas vezes o MySQL, e aí aparece ‘Error establishing a database connection’.

Os sinais: swap em uso no free -m e ‘Out of memory’ ou ‘Killed process’ em dmesg -T ou journalctl -k. Regra prática: fila com memória sobrando pede mais processos; memória no teto pede menos. Para acompanhar isso continuamente, veja monitoramento de VPS.

Quando aumentar pm.max_children não resolve: processo esperando terceiro ou banco

Subir o limite não basta em dois casos:

  • Processo esperando terceiro. Com API de frete, gateway ou antifraude lentos, o processo fica parado segurando memória. Mais processos só engrossam a fila no mesmo serviço, como mostra o artigo sobre checkout lento no pico.
  • Banco no teto. Mais processos PHP mandam mais consultas para um recurso único e pioram o gargalo. Veja gargalo de banco MySQL na VPS.

Para saber qual é o seu caso, ligue o slow log no arquivo do pool: request_slowlog_timeout = 5s e slowlog apontando para um arquivo. Cada requisição mais lenta que isso grava o rastro do código, mostrando onde travou. Se ele aponta para chamada HTTP externa ou consulta ao banco, o problema não é o número de processos.

Outro sinal: depois de aumentar o limite, o tempo de resposta sobe junto com a fila. Antes de dimensionar, confira se a fila é de cliente ou de robô com a análise de logs do servidor.

Limite calculado, memória no fim e pico maior que a VPS: onde o burst entra

Limite calculado pela memória, sem swap, requisições rápidas, banco com folga, e mesmo assim o aviso aparece no pico: aí a máquina acabou de verdade.

Restam duas saídas: um plano maior de VPS, pago o mês inteiro, ou capacidade extra só nas horas de pico. A comparação está em servidor maior ou reforço só no pico.

No burst, servidores extras sobem na nuvem pública durante o pico e são removidos quando a demanda cai. Cada um traz memória e cota de processos PHP-FPM próprias, então a capacidade se soma em vez de todos disputarem a mesma RAM.

Para isso, a aplicação precisa rodar em contêiner, e sessão e upload precisam sair do disco local (veja estado local em múltiplos servidores). Se o slow log apontou terceiro ou banco, o burst não ajuda: só multiplica as requisições presas.

Falta servidor ou falta a conta dos processos?

Com ‘server reached pm.max_children’ e CPU tranquila, a primeira suspeita é a conta, não a máquina. Meça a memória por processo, desconte sistema, banco, cache e margem, e ajuste o limite. Se o aviso persiste com a memória no fim e as requisições rápidas, aí sim falta servidor.

Conversar no WhatsApp para avaliar se o seu caso é de conta de processos ou de falta de máquina

Perguntas frequentes

O que significa ‘server reached pm.max_children’ no log do PHP-FPM?

Significa que todos os processos PHP-FPM que atendem cliente estão ocupados e as próximas requisições esperam na fila. Se a espera fica longa, o visitante recebe 502 ou 504.

Qual é a diferença entre pm = static, dynamic e ondemand?

Static mantém sempre o número máximo de processos abertos, ideal para VPS dedicada à loja. Dynamic mantém uma faixa entre mínimo e máximo, ajustada por configurações. Ondemand abre processo quando chega requisição e o fecha depois de um tempo parado. Os três modos respeitam o mesmo teto, pm.max_children.

Como calcular o pm.max_children certo para a minha VPS?

Meça a memória real de cada processo PHP-FPM com ps ou smem durante o pico. Depois faça a conta: (memória total − sistema operacional − banco de dados − cache − margem de segurança) ÷ memória média por processo. Arredonde sempre para baixo e mantenha margem de segurança para os processos mais pesados.

Por que a loja fica lenta ou dá 502 se a CPU está ociosa?

Porque faltou atendente (processo PHP-FPM livre), não processador. Quando todos os processos estão ocupados, a requisição espera na fila. Se a fila transborda, recebe 502; se a espera passa do tempo limite do nginx, recebe 504.

Aumentar pm.max_children pode derrubar o servidor?

Sim, se o limite ficar acima do que a memória comporta. O sistema passará a usar swap, que é muito mais lento, e o OOM killer pode matar processos importantes como o MySQL. A regra prática: fila com memória sobrando pede mais processos, e memória no teto pede menos.