How many PHP workers? Rereading my 2012 PHP-FPM config

Nine days after the Varnish post, in July 2012, I wrote PHP Offloading… Nginx helps so much!. It explains why nginx beats Apache for Magento (“we are all about performance aren’t we?”), then hands over an nginx server block and a PHP-FPM pool with “of course suggestions are welcome”. Fourteen years on, here are mine. The pool starts like this: pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 50 pm.max_requests = 500 Fifty. The post never says where 50 came from, and that one number decides whether the box runs flat out or falls over. So this is mostly about how to pick it, with two things the rest of that config got quietly wrong along the way. ...

September 24, 2026 · 7 min · Luis Tineo

Rereading my 2012 nginx config: the block that runs your uploads

The PHP-FPM reread ended on a promise. The same July 2012 post, PHP Offloading… Nginx helps so much!, hands over an nginx server block, and one location in it has a problem that has nothing to do with performance: location ~ .php$ { ## Execute PHP scripts if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss ... fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; ... } “Execute PHP scripts” is exactly what it does. Any request ending in .php goes to PHP-FPM, and PHP-FPM runs whatever file nginx names. Nobody asks whether that file was ever meant to be a script. So if somebody can get a .php file into a folder the web server serves, through an avatar upload, an import, a product image field that checks the extension a bit too loosely, that file runs. ...

September 24, 2026 · 3 min · Luis Tineo