keepcalculator

06 Numbers and Powers

Optimize Apache & LAMP RAM Usage

Card No. 06·8085 · Updated · Standard formula, shown below

This guide walks you through reducing the memory footprint of Apache and the rest of a LAMP stack (Linux, Apache, MySQL/MariaDB, PHP). You’ll learn how to tune Apache’s multi-processing modules, cap PHP worker memory, and adjust MySQL buffers so your server can handle more traffic without swapping to disk. No prior tuning experience is needed, but you should have root or sudo access to the server.

What You’ll Need

  • Root or sudo access to your Linux server
  • Apache, MySQL/MariaDB, and PHP already installed and running
  • Command-line access (SSH)
  • A text editor (nano, vim, or similar)
  • Basic familiarity with editing config files

Step-by-Step

  1. Check current memory usage. Run free -h to see total and used RAM. Then run ps aux --sort=-%mem | head -20 to list the top memory consumers. Note which processes (apache2, mysqld, php-fpm) are using the most.
  2. Identify your Apache MPM. Run apache2ctl -V | grep MPM (on Debian/Ubuntu) or httpd -V | grep MPM (on RHEL/CentOS). You’ll see either prefork, worker, or event. The MPM determines how Apache handles connections and how much memory each process uses.
  3. Switch to the event MPM if possible. The event MPM is the most memory-efficient for most workloads, especially with PHP-FPM. On Debian/Ubuntu, run sudo a2dismod mpm_prefork && sudo a2enmod mpm_event. On RHEL/CentOS, edit /etc/httpd/conf.modules.d/00-mpm.conf and comment/uncomment the correct LoadModule line. Restart Apache after changing.
  4. Tune Apache’s process limits. Edit your Apache config (usually /etc/apache2/apache2.conf or /etc/httpd/conf/httpd.conf). Look for the <IfModule mpm_*_module> block. Set MaxRequestWorkers to a value that fits your RAM. A safe starting point: divide your available RAM (in MB) by the average memory per Apache process (check with ps aux | grep apache). For example, if you have 2GB RAM and each process uses 30MB, set MaxRequestWorkers to around 50. Also set MinSpareThreads and MaxSpareThreads to low values (e.g., 5 and 10) to avoid idle processes.
  5. Switch PHP to PHP-FPM. PHP as an Apache module (mod_php) is memory-hungry because it runs inside every Apache process. PHP-FPM runs PHP separately and is more efficient. Install php-fpm, then disable mod_php: sudo a2dismod php7.4 (adjust version) and enable the proxy modules: sudo a2enmod proxy_fcgi setenvif. Then configure Apache to pass PHP requests to PHP-FPM. On Debian/Ubuntu, you can use sudo a2enconf php7.4-fpm. Restart Apache and PHP-FPM.
  6. Limit PHP-FPM memory. Edit /etc/php/7.4/fpm/pool.d/www.conf (or similar). Set pm = dynamic, pm.max_children to a number that fits your RAM (e.g., 20), pm.start_servers to 5, pm.min_spare_servers to 5, and pm.max_spare_servers to 10. Also set php_admin_value[memory_limit] = 128M (or lower if your app works with less). Restart PHP-FPM.
  7. Optimize MySQL/MariaDB memory. Edit /etc/mysql/my.cnf or /etc/my.cnf. The most important settings are key_buffer_size (for MyISAM, set to 16-32MB), innodb_buffer_pool_size (for InnoDB, set to about 25% of your RAM, e.g., 512MB for 2GB RAM), and query_cache_size (set to 0 or a small value like 16MB; the query cache is deprecated in MySQL 8). Also set max_connections to a reasonable number (e.g., 50). Restart MySQL.
  8. Monitor and adjust. After each change, restart services and run free -h again. Watch for swap usage (swapon --show). If swap is used, reduce your limits further. Use top or htop to see if any process is consuming too much.
  9. Consider using a lightweight alternative for static files. If you serve a lot of static content (images, CSS, JS), offloading it to a lightweight server like Nginx or Varnish can free up Apache memory. This is more advanced but very effective.

Common Mistakes

  • Setting MaxRequestWorkers too high. This is the most common mistake. If you set it too high, Apache will spawn more processes than your RAM can handle, causing swapping and a slow server.
  • Keeping mod_php when using PHP-FPM. If you don’t disable mod_php, Apache will still load PHP into every process, negating the memory savings.
  • Setting innodb_buffer_pool_size too large. This buffer is allocated at startup. If you set it to 80% of RAM, MySQL will use most of your memory, leaving little for Apache and PHP.
  • Ignoring swap usage. If you see swap being used, your server is memory-constrained. Reduce limits immediately.
  • Not restarting services after config changes. Changes only take effect after a restart.

Tips

  • Use a tool like ps_mem to get accurate per-process memory usage. Install it with sudo apt install ps_mem or sudo yum install ps_mem and run sudo ps_mem to see a clean summary.
  • Start with low values and gradually increase. It’s easier to add more capacity than to fix a server that’s swapping.
  • Consider using a CDN for static files. This reduces the load on your server entirely.
  • Use systemctl status to verify services are running after restarts.
  • Keep a backup of your config files before editing.

Troubleshooting

Apache won’t start after changing MPM. Check the error log (/var/log/apache2/error.log or /var/log/httpd/error_log). You may need to re-enable mod_php if you’re using PHP-FPM incorrectly. Ensure the proxy_fcgi module is enabled.

PHP scripts download instead of executing. This usually means the proxy_fcgi configuration is wrong. Check that your virtual host has the correct SetHandler directive, e.g., SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost".

MySQL fails to start after changing buffer sizes. Check the MySQL error log (/var/log/mysql/error.log). The buffer size may be too large for your system’s shared memory. Reduce it and try again.

Server still swaps. Use ps aux --sort=-%mem to find the culprit. It might be another service, not Apache. Consider adding swap space (sudo fallocate -l 2G /swapfile) as a temporary measure, but the goal is to reduce memory usage.

Apache is slow after reducing MaxRequestWorkers. If you set it too low, requests will queue up. Check apache2ctl status to see if there are many waiting requests. Increase the value slightly, but watch memory.

Frequently Asked Questions

Q: What is the best MPM for Apache? The event MPM is generally the best for performance and memory, especially with PHP-FPM. Prefork is only needed for older PHP modules that are not thread-safe.

Q: How much memory should I allocate to MySQL? A common rule of thumb is 25% of available RAM for InnoDB buffer pool. But this depends on your data size and workload. Start low and monitor.

Q: Is PHP-FPM always better than mod_php? Yes, for memory usage, PHP-FPM is almost always better because it separates PHP processes from Apache, allowing Apache to be more efficient. The only exception is if you have a very simple server with minimal traffic.

Q: What is the difference between MaxRequestWorkers and MaxClients? They are the same thing in Apache 2.4. In older versions, MaxClients was used. The directive was renamed to MaxRequestWorkers.

Q: Can I use Nginx instead of Apache? Yes, Nginx is more memory-efficient for static files and can also handle PHP via PHP-FPM. But switching is a bigger change. You can also run Nginx as a reverse proxy in front of Apache to offload static content.

Q: How do I know if my server is swapping? Run swapon --show to see if swap is in use. Also free -h will show swap usage. If the ‘used’ column is high, you may be swapping.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →