Se o Apache congela, 99% das vezes é porque você deixou ele spawnar mais processo do que sua RAM aguenta. Simples assim.
1) Descubra quanto cada processo consome
Antes de sair chutando número:
ps aux | grep apache2
ou:
ps -ylC apache2 --sort:rss
Olha o RSS (memória). Exemplo realista:
60MB por processo
Guarda isso.
2) Calcule o limite REAL de processos
Regra prática (sem romantismo):
RAM disponível / memória por processo = MaxRequestWorkers
Exemplo:
- 2GB RAM livre
- 60MB por processo
2000 / 60 = ~33 processos
Configura no máximo ~30, não 150 igual tutorial lixo.
3) Ajustes no MPM (isso aqui é o core do problema)
Se usa prefork (com mod_php velho)
Arquivo:
/etc/apache2/mods-enabled/mpm_prefork.conf
Configuração decente:
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 30
MaxConnectionsPerChild 300
</IfModule>
Explicação rápida (sem aula):
- MaxRequestWorkers → limite de processos (o mais importante)
- MaxConnectionsPerChild → mata processo antes de vazar memória
- Start/Spare → só controle de spawn, não é gargalo
4) Se ainda usa prefork… pare
Prefork + mod_php = consumo absurdo.
Vai pra:
mpm_event+ PHP-FPM
Ativa:
a2dismod mpm_prefork
a2enmod mpm_event proxy_fcgi setenvif
a2enconf php8.2-fpm
5) Ajuste o PHP-FPM (onde a RAM morre de verdade)
Arquivo:
/etc/php/8.2/fpm/pool.d/www.conf
Parâmetros chave:
pm = dynamic
pm.max_children = 30
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
Mesma lógica:
pm.max_children = limite baseado na RAM
Se errar aqui, não importa o Apache — vai travar igual.
6) Timeout: corta requisição zumbi
Timeout 30
Evita request pendurado segurando worker.
7) KeepAlive (ajuste fino, mas ajuda)
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2
Timeout alto = conexão segurando worker à toa.
8) Evite leak infinito
Apache:
MaxConnectionsPerChild 300
PHP-FPM:
pm.max_requests = 500
Isso força reciclagem → evita consumo crescente.
9) Swap NÃO é solução
Se entrou swap:
já perdeu performance
Swap é airbag, não motor.
10) Teste carga (não seja amador)
ab -n 1000 -c 50 http://localhost/
ou melhor:
wrk -t4 -c50 -d30s http://localhost/
Se travar aqui, ia travar em produção.
TL;DR (pra quem lê log, não tutorial)
- Descobre consumo real por processo
- Calcula limite baseado na RAM
- Ajusta
MaxRequestWorkers/pm.max_children - Mata processos periodicamente
- Usa
mpm_event + PHP-FPM - KeepAlive curto
- Timeout baixo
Erro clássico (pra evitar vergonha)
- Colocar
MaxRequestWorkers 500em VPS de 2GB - Usar prefork em 2026
- Ignorar PHP-FPM
- Achar que CPU é o problema (quase nunca é)
