How Many PHP Workers Does Shared Hosting Need for Fast Sites

How Many PHP Workers Does Shared Hosting Need for Fast Sites

Shared hosting usually gives you a fixed number of PHP-FPM worker processes, and the right number for a fast site is almost always more than you think, but far fewer than the server can physically run. The practical answer is this: you need enough workers to cover your peak concurrent PHP requests without queueing, but not so many that memory pressure forces the kernel to swap. For a typical WordPress or WooCommerce site on shared infrastructure, that number is often between 4 and 12 workers, and you can measure it directly instead of guessing.

Why PHP Workers Are the Bottleneck, Not the Web Server

When a visitor hits your site, the web server (usually Apache or Nginx) receives the request and passes it to PHP-FPM. PHP-FPM maintains a pool of worker processes, each one capable of executing one PHP script at a time. If all workers are busy, new requests wait in a queue. The queue is where your site dies: response times jump from 200 milliseconds to 5 seconds, and the browser keeps the connection open, which makes the problem worse because the web server now holds more threads and sockets.

The pm.max_children directive in your PHP-FPM pool configuration sets the hard cap on concurrent PHP executions. On shared hosting, you rarely control this value directly, because the host manages the pool per account or per site. But you can often see the effective value through a status page or a command line tool. The key is to understand that the number of workers is a tradeoff between latency and memory. Each worker reserves a chunk of RAM, typically between 20 and 60 MB for a modern PHP 8 application, depending on the framework and the extensions loaded.

How to Measure What Your Site Actually Needs

Do not rely on the host's default settings or on generic advice from blog posts. Run a load test against your own site, but do it carefully, because shared hosting is a shared resource and a full blast test can get you suspended. Instead, use a controlled approach with a tool like ab (ApacheBench) or wrk, sending a small number of concurrent requests and watching the PHP-FPM status page.

First, enable the status page in your pool configuration, if the host allows it. Add this to your pool file, usually located in /etc/php/8.2/fpm/pool.d/www.conf:

pm.status_path = /status

Then reload PHP-FPM and make a request to that path from the command line. The output will show you the current state, the number of active processes, and the queue length. Run this while you send traffic to your site. Here is the shape of a typical response:

pool:                 www
process manager:      dynamic
start time:           12/Jan/2025:10:30:00
start since:          3600
accepted conn:        12000
listen queue:         2
max listen queue:     15
listen queue len:     0
idle processes:       3
active processes:     5
total processes:      8
max active processes: 9
max children reached: 0

Watch the listen queue value. If it stays at zero during your test, you have spare capacity. If it grows above a few requests, you need more workers. The max children reached counter tells you how many times PHP-FPM had to refuse a new worker because it hit the limit. If that number increases during a traffic spike, your pool is too small.

The Config Directives That Control Worker Count

PHP-FPM offers three process management modes: static, dynamic, and ondemand. Shared hosting almost always uses dynamic or ondemand, because the host wants to minimize memory usage when your site is idle. In dynamic mode, the relevant directives are pm.max_children, pm.start_servers, pm.min_spare_servers, and pm.max_spare_servers. The host sets these, but you can often override them in a .user.ini file or a per-site pool file, depending on the control panel.

For a typical small business site, a good starting point is pm.max_children = 8 with pm.start_servers = 2 and pm.max_spare_servers = 4. That gives you enough headroom for a sudden burst of traffic without reserving memory for workers that sit idle all day. If your site uses a lot of memory per request, for example a heavy page builder or a large media library, drop the number to 5 or 6. If your site is lean, you can go up to 12, but only if the server has the RAM to spare.

Remember that each worker also holds persistent connections to MySQL and often to Redis or Memcached. A dozen PHP workers can open a dozen database connections, and the database server on shared hosting has its own connection limit. If you see Too many connections errors from MySQL, that is a sign that your worker count is too high for the database, not just for the web server.

What Happens When You Exceed the Limit

When all workers are busy and the queue fills up, PHP-FPM starts rejecting new requests with a 503 Service Unavailable response. The web server may also return a 502 Bad Gateway if it cannot connect to PHP-FPM at all. From the visitor's perspective, the site appears down. From the server's perspective, the CPU may still be low, because the workers are all stuck waiting on database queries or external API calls, not doing heavy computation. This is why simply adding more CPU power does not fix a worker shortage.

Look at the max children reached counter again. If it increments during a normal day, your pool is undersized. But also check the max active processes value. If that number is consistently close to max_children, you are running at the edge. If it is lower than your cap by a wide margin, the occasional 503 you see is probably caused by a spike that lasted a few seconds, and adding a couple of workers will smooth it out.

Practical Steps to Tune Your Pool

Start by checking the current configuration. Run php-fpm -i or look at the pool file directly. If you cannot edit the pool file, ask your host to raise the limit, and give them the exact numbers from your status page as evidence. Do not ask for "more resources" in the abstract. Show them that listen queue went to 15 and max children reached went to 3 during a specific traffic test.

If you can make changes yourself, change one directive at a time and rerun the load test. Increase pm.max_children by 2, reload PHP-FPM, and watch the status page for five minutes. Watch the memory usage on the server with free -m or htop. If the server starts using swap, back off immediately, because swapping will make your site slower than a short queue ever would.

Also consider the application layer. A WordPress site with a good page cache plugin will rarely need more than 6 workers, because most requests are served from static HTML files. A WooCommerce store with active carts and a live inventory system will need more, because every request touches the database. A custom Laravel or Symfony app with heavy API calls can need 10 or more, but it will also benefit more from queueing at the application level, for example with a job queue, than from more PHP workers.

What to Do Next

Run your own load test with a realistic traffic pattern, not a synthetic benchmark. Use a tool like wrk or ab with a concurrency level of 10 to 20, and watch the PHP-FPM status page while you do it. Record the listen queue and max children reached values. Then adjust your pool configuration or send those numbers to your host. Repeat the test after each change until the queue stays near zero and the server stays off swap. That is the right number of PHP workers for your shared hosting plan, and it is a number you can defend with data, not a guess.

Related articles

Subscribe to our newsletter

Get the latest hosting tips, performance insights, and industry news.