Have you ever wondered if Apache
mod-php is faster than
php-fpm with Nginx? I surely did.
Each time this question arises, I do a quick research, and I cannot seem to find a definitive answer. It seems that the recommended way to run PHP websites nowadays is to use
php-fpm with Nginx, but is that the best method? Some articles state that
php-fpm is 300% faster than
mod-php, other articles state that
mod-php is faster, and so on.
This is why I've decided to conduct my own tests and performance benchmark and settle this debate once and for all.
The result surprised me.
The test environment
- Machine: Hetzner VPS with 2 dedicated AMD CPUs, 8GB RAM, 80GB SSD
- Benchmark machine: separate VPS (in the same region)
- Benchmark tool: bombardier (golang)
- OS: Ubuntu 22.04
- PHP version: PHP 8.2.9
- mod-php web server: Apache/2.4.52 with mod-php 8.2.9
- php-fpm web server: nginx/1.18.0 with php-fpm 8.2.9
- php.ini custom config:
// php.ini // default config opcache.memory_consumption=256 opcache.max_accelerated_files=20000 opcache.validate_timestamps=0 realpath_cache_size=4096K realpath_cache_ttl=600
This is the suggested PHP configuration for maximum performance for Symfony production environments.
Both servers use the same php.ini file!
Apache mpm prefork module configuration
# /etc/apache2/mods-available/mpm_prefork.conf StartServers 5 MinSpareServers 50 MaxSpareServers 100 MaxRequestWorkers 150 MaxConnectionsPerChild 0
I've deliberately chosen a high value for
MinSpareServers because more spare servers mean fewer cold starts and better performance in general.
Nginx process manager configuration
; /etc/php/8.2/fpm/pool.d/www.conf pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 pm.max_requests = 500
The test app
I chose Symfony PHP framework for the test app, and I've created a simple app with one page that renders some text. No database queries because they can distort the results.
The exact command to run the tests is
bombardier -c 200 -d 1m -l http://IP_HERE/
which translates to
- Concurrent requests: 200
- Duration: 1 minute
Let's see how both methods compare in each category.
Average requests per second
In the average requests per second, the race is neck to neck with Nginx
php-fpm having a slight advantage.
In the average latency, Nginx with php-fpm again has a slight advantage over Apache mod php.
In the max latency category, things get a little bit more interesting.
It seems that Apache mod-php has a maximum latency of 10 seconds. I'll repeat - 10 seconds where Nginx php-fpm has a max latency of only 320.16ms.
Ten seconds of latency for a simple page is terrible and concerning.
Nginx php-fpm here is a clear winner by a lot.
Apache mod-php had 205 timeouts, whereas Nginx php-fpm had ZERO.
Again, Nginx php-fpm is the clear winner here.
Also, having that many timeouts is a bit concerning. That tells me the Apache limit was reached.
Nginx php-fpm latency distribution
Nginx php-fpm shows stable latency distribution, which is a good thing! This means the performance is solid without fluctuations.
Apache mod-php latency distribution
I can't tell the same about Apache mod-php.
The latency distribution has a lot of fractionations. Again, this shows the Apache limit was reached.
root@ubuntu-test-bench:~# bombardier -c 200 -d 1m -l http://phpfpm/ Bombarding http://phpfpm:80/ for 1m0s using 200 connection(s) [===========================================] 1m0s Done! Statistics Avg Stdev Max Reqs/sec 781.55 57.29 993.02 Latency 255.43ms 9.08ms 320.16ms Latency Distribution 50% 255.28ms 75% 257.38ms 90% 259.49ms 95% 261.25ms 99% 269.54ms HTTP codes: 1xx - 0, 2xx - 47070, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 0.90MB/s root@ubuntu-test-bench:~# bombardier -c 200 -d 1m -l http://modphp/ Bombarding http://modphp:80/ for 1m0s using 200 connection(s) [===========================================] 1m0s Done! Statistics Avg Stdev Max Reqs/sec 690.88 130.38 3421.26 Latency 289.55ms 0.86s 10.03s Latency Distribution 50% 200.18ms 75% 270.75ms 90% 358.24ms 95% 401.93ms 99% 1.83s HTTP codes: 1xx - 0, 2xx - 41425, 3xx - 0, 4xx - 0, 5xx - 0 others - 205 Errors: timeout - 205 Throughput: 790.21KB/s
The performance tests and benchmarks have provided valuable insights into the comparison between Nginx with PHP-FPM and Apache with mod_php. The results point toward Nginx PHP-FPM as the clear winner in terms of performance and stability.
Nginx PHP-FPM stands out with better metrics such as higher average requests per second and lower average latency. It also excels in avoiding prolonged delays, as evidenced by its lead in maximum latency over Apache mod_php.
Additionally, Nginx PHP-FPM is more reliable under pressure, as it doesn't experience timeouts like Apache mod_php, which had 205 timeouts. Nginx PHP-FPM's stable latency distribution further demonstrates its consistent performance, while Apache mod_php appears to struggle.
In summary, developers looking for both performance and reliability are encouraged to choose Nginx with PHP-FPM. These findings provide valuable guidance for optimizing web server configurations to enhance user experiences and improve application performance.