What you're experiencing is a classic memory leak scenario in Apache. The key indicators are:
- Steady memory increase despite stable traffic
- No memory release after requests complete
- Eventually leads to server crashes
For a 4GB server, let's start with these fundamental settings in httpd.conf:
StartServers 2
MinSpareServers 2
MaxSpareServers 5
MaxClients 10
MaxRequestsPerChild 300
Your current setup appears to be using prefork. Consider switching to worker MPM for better memory efficiency:
<IfModule mpm_worker_module>
ServerLimit 4
StartServers 2
MaxClients 10
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>
If you're running PHP with Apache, these php.ini adjustments help:
memory_limit = 64M
max_execution_time = 30
realpath_cache_size = 128k
Install mod_status for real-time monitoring:
<Location /server-status>
SetHandler server-status
Require host localhost
</Location>
Then access via http://localhost/server-status
Create a cron job to automatically restart Apache when memory exceeds 3GB:
#!/bin/bash
THRESHOLD=3000000
APACHE_MEM=$(ps -ylC apache2 | awk '{mem += $8} END {print mem}')
if [ $APACHE_MEM -gt $THRESHOLD ]; then
/etc/init.d/apache2 restart
fi
For persistent issues, consider:
- Implementing a reverse proxy with Nginx
- Moving static content to CDN
- Using PHP-FPM instead of mod_php
Enable detailed logging to identify memory-heavy requests:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %D %k" debug_log
CustomLog /var/log/apache2/debug.log debug_log
From your top output, I can see each Apache process is consuming ~322MB of virtual memory, with ~37MB resident. Your calculation approach is correct but needs refinement:
# More precise MaxClients calculation:
Total Available RAM = 4000MB
OS/Other Services = 1000MB (estimated)
Available for Apache = 3000MB
Per-process RAM = 37MB (RES column)
MaxClients = 3000/37 ≈ 80
For a 4GB server running prefork (common for PHP environments), try these httpd.conf settings:
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 50 # Conservative starting point
MaxRequestsPerChild 1000 # Helps prevent memory leaks
If you're using worker/event MPM (common for modern setups):
ServerLimit 16
StartServers 2
MaxClients 400
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 10000
Your update about growing memory usage suggests either:
- PHP memory leaks (common with poorly written extensions/plugins)
- Apache module issues (try disabling unused modules)
Debug steps:
# Monitor PHP memory usage:
<?php
memory_get_peak_usage(true)/1024/1024 . "MB\n";
?>
# Apache module cleanup:
apachectl -t -D DUMP_MODULES
# Disable unnecessary modules like mod_rewrite if unused
When Apache starts swapping, performance tanks. Add this to prevent:
# In /etc/sysctl.conf
vm.swappiness = 1
vm.overcommit_memory = 1
For WordPress on 4GB RAM:
# .htaccess memory limit
php_value memory_limit 128M
# httpd.conf additions
<IfModule prefork.c>
StartServers 3
MinSpareServers 5
MaxSpareServers 10
MaxClients 30
MaxRequestsPerChild 500
</IfModule>
Remember to restart Apache after changes and monitor with:
watch -n 1 "ps -ylC apache2 --sort:rss | awk '{print $8}'"