Optimizing PHP7 with nginx

Posted May 27, 2017 18.6k views
NginxPHPPHP FrameworksUbuntu 16.04

i know there are tons of articles around the web for such topic, but i really dont like to tune my server just with given figures without understanding it.

also i highly rely on this community as most of all guides are very details. also thanks to @jtittle & @hansen for their excellent support.

basically my server has separate web server & database server (both are 1gb each)

and i also have 2 pools, 1 for my main site/community(wordpress), another for my application(codeigniter) which is on a sub-domain.

the application is going to be using most of the resources i assume (even though its on codeigniter framework which is already very lightweight), as main site is not that large, and on top of that its fastcgi enabled.

so what should be the pools configuration for my setup?

till now i didnt changed the default value, so both pools are running on the same value. but after googling a lot, i think this could be a good setting for my 2 php pools.

For Both site

emergency_restart_threshold 10
emergency_restart_interval 1m
process_control_timeout 10s

Main site

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 300
request_slowlog_timeout = 5s
slowlog = /var/log/php/7.0/fpm/slowlog-site.log

PHP Application

pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 500
request_slowlog_timeout = 5s
slowlog = /var/log/php/7.0/fpm/slowlog-app.log

Please reply here your recommendation guy’s.

thanks in advance.

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Submit an Answer
2 answers


When it comes to PHP-FPM configuration, I generally to stick close to the defaults with a few minor changes unless there’s a need to modify settings further (i.e. higher levels of traffic).

** rlimit_files**

This setting defines the open file descriptor rlimit for the master process. I’d set to this something such as 65536, though you’ll also need to make sure you set this at the OS level as well as defaults are generally 1024.

Inside your PHP-FPM configuration, you’d define:

rlimit_files = 65536
rlimit_core = 0

You’d then need to open up /etc/security/limits.conf.


#<domain>      <type>  <item>         <value>

And below it, add something such as:

httpd    soft    nofile    4096
httpd    hard    nofile    65536

You’ll want to set this per user, and would change httpd to the user in your PHP-FPM config. So if you have mainuser and appuser, you’d use:

appuser     soft    nofile    4096
appuser     hard    nofile    65536
mainuser    soft    nofile    4096
mainuser    hard    nofile    65536


This setting limits PHP-FPM to executing files with the .php extension, if defined. It’s a good idea to set or define this directive and that can be done using:

security.limit_extensions = .php

Beyond that, I wouldn’t really prematurely try to optimize PHP-FPM until you start noticing issues or there’s a need. Like most services, you could easily exhaust resources with settings that try to start too many processes.

With FastCGI Caching enabled, you can honestly get by with the defaults or just slight changes as the cache is going to reduce a lot of what the service would normally need.

When you have FastCGI Caching enabled, NGINX is serving the static files, not PHP, so once a file is cached, NGINX is taking over until the cache expires or is purged – then the first request is going to result in a cache HIT, and the process repeats.

  • @jtittle
    i didnt understand this part actually

    though you'll also need to make sure you set this at the OS level as well as defaults are generally 1024.

    did you meant by changing worker connection in etc/nginx/nginx.conf

    worker_connections   1024; to 65536
    • @newbie

      Changing it at the OS level would be modifying /etc/security/limits.conf :-).

      • @jtittle

        so this should be added to /etc/security/limits.conf?

        rlimit_files = 65536
        rlimit_core = 0
        httpd    soft    nofile    4096
        httpd    hard    nofile    65536
        security.limit_extensions = .php
        • @newbie

          The first two and last line, no – those are PHP-FPM pool directives and are set in the pool configuration file, which would be either www.conf, or one you created.

          The changes that go in /etc/security/limits.conf are per user

          httpd, appuser, and mainuser are just examples that you could use, if they were valid users – in most cases they wouldn’t be, so you’d need to substitute in your own users (i.e. those you define per pool configuration for PHP-FPM – those that are defined by the user directive).

          A better example might be:

          www-data    soft    nofile    4096
          www-data    hard    nofile    65536

          …or if I had a user jtittle on my system:

          jtittle    soft    nofile    4096
          jtittle    hard    nofile    65536


          You’re modifying two different files, so it’s definitely important not to get the two mixed up :-).

I do prefer on demand setup, so process get always killed and freshly restarted when not in use.
pm = ondemand

And please watch your pm.max_children, 10 + 5 (15) it is way over for your 1G ram server. You assume that each process will take no much than 68.26 MB … and this calculation is wrong, I did not remove the base memory of your system and a buffer to don’t blow the things up.

Before explaining how to calculate the pm.max_children, have you created a swap memory on your server? You should, backup ram to avoid server bust…

Ubuntu (2 GB):
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo “/swapfile none swap sw 0 0”>>/etc/fstab
free -m

Ok now the calculation of pm.max_children:
[Total RAM] - [Server idle mem] - [buffer: (Total RAM * 0.1)] = PHP-fpm available memory

So in your case lets say you want at least 128 Megs per process (children)
1024 - 140 - (10240.1) = *782** MB PHP-fpm available memory

So you still want 128 Megs per process…
782 / 128 = 6

So you got pm.max_children = 6 to divide into your 2 applications you got.... 2 / 4? 3 / 3?

Note that if children are all busy, request are going to a queue… Way better then overloading your server memory and having your server not responding at all…