If you have deployed a LEMP (Linux, NGINX, MySQL/MariaDB, and PHP) stack, then you are probably using FastCGI proxying within NGINX (as an HTTP server), for PHP processing. PHP-FPM (an acronym of FastCGI Process Manager) is a widely-used and high-performance alternative PHP FastCGI implementation.
Here are the useful guides on setting up LEMP Stack in Linux.
- How to Install LEMP Stack with PhpMyAdmin in Ubuntu 20.04
- How to Install LEMP Server on CentOS 8
- How to Install LEMP on Debian 10 Server
Recently, all our PHP websites on one of our LEMP web servers became slow and eventually stopped responding on logging into the server. we discovered that the system was running low on RAM: PHP-FPM had consumed most of the RAM, as indicated in the following screenshot (glances – system monitoring tool).
In this article, we will show how to prevent PHP-FPM from consuming too much or all your system memory (RAM) in Linux. At the end of this guide, you will learn how to reduce PHP-FPM memory consumption by 50% or more.
Reduce PHP-FPM Memory Usage
After doing some research on the Internet, we discovered that we needed to reconfigure the PHP-FPM process manager and certain aspects of it to reduce PHP-FPM’s memory consumption in the pool configuration file.
The default pool is www and its configuration file is located at /etc/php-fpm.d/www.conf (on CentOS/RHEL/Fedora) or /etc/php/7.4/fpm/pool.d/www.conf (on Ubuntu/Debian/Mint).
$ sudo vim /etc/php-fpm.d/www.conf [On CentOS/RHEL/Fedora] $ sudo vim /etc/php/7.4/fpm/pool.d/www.conf [On Ubuntu/Debian/Mint]
Find the following directives and set their value to suit your use case. For directives that are commented out, you need to uncomment them.
pm = ondemand pm.max_children = 80 pm.process_idle_timeout = 10s pm.max_requests = 200
Let’s briefly explain the above directives and their values. The pm directive determines how the process manager will control the number of child processes. The default method is dynamic, which means the number of children (child processes) is set dynamically depending on some other directives including pm.max_children which defines the maximum number of children that can be alive at the same time.
The most ideal process manager is the ondemand scheme where no child processes are created at startup but are spawned on demand. Child processes are only forked when new requests will connect based on the pm.max_children and pm.process_idle_timeout which defines the number of seconds after which an idle process will be killed.
Last but not least, we need to set the pm.max_requests parameter which defines the number of requests each child process should execute before re-spawning. Note that this parameter can also be used as a workaround for memory leaks in 3rd party libraries.
Reference: A better way to run PHP-FPM.
After making these above configurations, I noticed RAM usage is now fine on our server. Do you have any thoughts to share related to this topic or questions? Reach us via the feedback form below.
12 thoughts on “How To Prevent PHP-FPM From Consuming Too Much RAM in Linux”
I am using CentOS 7 and maybe i have installed php-fpm in a different way and for the default pool www configurations file is located at /etc/opt/rh/rh-php72/php-fpm.d/www.conf.
So I set php max request to 100 and memory is ok now.
Thanks for the tips
But how to select the value if I am not an expert? any tips? I am using 8GB, 4 Core NVMe VPS with cent0s 7, having AVG 10K daily visitors. (paid traffic/ wordpress site)
Worth reading just to find out about glances. Regardless of whether this is good for production or only for development, this pointed me in the right direction and at least now I know what to look at.
I hope that this comment will not be ignored in the moderation queue.
Please do yourself a favor and disregard the advice in this article.
The ondemand mode will introduce delays for users because right after the start there is no PHP process that can handle the request. The server needs to start a process, this takes time and that time the user has to wait.
The max_request is too low and will amplify these delays for users because after 200 requests the process will kill itself. The idle_timeout of 10 seconds will further amplify the delay problems because after 10 seconds of no requests the process will kill itself.
With this config, you successfully reduced the RAM usage. But you also made the user experience worse because you tell your server to kill all PHP processes after a short amount of time.
You have to balance these settings to something that doesn’t overload your server, and you should never get to the situation where there are no PHP processes on the server to handle your user’s requests! In this article, max_children is set to 80, which is very high. Is your server really able to handle 80 requests at the same time? If so, you should have plenty of RAM and you don’t need the mentioned settings.
You also have to take into account that the RAM usage is not only from PHP but from your code written in PHP. If you think that you use too much RAM, look into your application if you can cut away things. In general, you want to have as much code and data as possible in RAM because RAM is fast. If you kill your PHP processes often you will handicap a lot of performance optimizations.
We are always open to discussion and insights such as this. We will do further investigations about the information shared in the guide in regards to your advice and review/update the article where possible. Many thanks for sharing your thoughts with us about this topic.
Great article and great notes from a commentator. This topic is highly debatable. @commentator – What have you found to work great for you on a 1GB RAM, 1CPU installation running woocommerce, or thereabouts?
@JB: with these specs (1 GB RAM, 1 CPU) it doesn’t matter. If you get a lot of users at once, your machine will choke, no matter what. The default settings will be fine. For more users (around 5 to 50 requests per second), you will need a better machine with more RAM and more CPU.
Nobody should use this configuration in production!
With this config, you successfully reduced the RAM usage. But you also made the user experience way worse.
You have to balance these settings to something that is okay for your server and you should never get to the situation where there are no PHP processes on the server to handle your users requests!
What should be the ideal PHP-FPM configuration for concurrency of 20000 hits? How does Apache configuration affects PHP-FPM results?
You can monitor the performance of PHP-FPM after making the above changes and adjust your configurations accordingly, to suit your use case. Secondly, I personally have no experience in using Apache with PHP-FPM, but you can find more information about this on the Internet.
Hi, ondemand is not recommended in the prod environment because you lose perfs on establishing a connection with php (you systematically have to wait for the creation of the process to execute code on the first connection). Not sure consuming less RAM but globally lose perfs is a good deal.
That’s why it’s preferable to use ondemand on dev env, eventually on test and staging but never on prod
We have put the ondemand process manager to the test, if the results are not satisfying or if it negatively impacts performance then we shall look for another solution, and also update this article accordingly. Thanks for sharing your thoughts with us.