Part of the Kinsta Review 2026: Best Managed WordPress Hosting? (Deep Dive) series
A PHP worker is a single process that executes your site's dynamic, uncached requests — cached pages use zero workers, but every cart addition, checkout, or login consumes one, which is why worker count (not traffic volume) determines capacity.
Key Takeaways
- A PHP worker is a single process that executes PHP code for one request at a time; cached pages skip PHP entirely and use zero workers.
- An average WordPress PHP-FPM worker uses roughly 40-80MB of RAM in 2026, which is why pm.max_children is capped by memory, not CPU count.
- One worker generally covers 1-2 uncached requests per second — a busy WooCommerce checkout window needs several workers running concurrently.
- Kinsta renamed 'PHP workers' to 'PHP threads' across its platform in December 2024; both terms describe the same underlying PHP-FPM process.
- Redis object caching cuts database wait time enough that each worker finishes 2-5x faster, raising effective site capacity without a bigger plan.
If you've shopped for managed WordPress hosting in the last few years, you've run into this pitch: "2 PHP workers on Starter, 4 on Business, 14+ on Enterprise." Kinsta and WP Engine both lead with the number on their pricing pages, right next to storage and visit limits.
A PHP worker is a single PHP process that executes your site's dynamic code and hands back a finished page. It's the resource that actually runs WordPress — not disk space, not bandwidth. Most site owners misread the spec sheet, though, and assume "2 workers" means only 2 visitors can be on the site at once. That's wrong for the 90%+ of traffic that hits a cache, and it's the reason so many people either overpay for capacity they don't need or get blindsided by 504 errors during a sale they did need it for.
This guide walks through the request lifecycle, the cached-vs-uncached split that actually determines your capacity, PHP-FPM's three worker-spawning modes, how to read your own server logs, and a sizing table by site type — plus a heads-up on terminology, because one major host quietly renamed "workers" to "threads" and a lot of guides online haven't caught up.
Key Takeaways
- A PHP worker is a single process that executes PHP code for one request at a time; cached pages skip PHP entirely and use zero workers.
- An average WordPress PHP-FPM worker uses roughly 40–80MB of RAM in 2026, which is why
pm.max_childrenis capped by memory, not CPU count. - One worker generally covers 1–2 uncached requests per second — a busy WooCommerce checkout window needs several workers running concurrently, not one.
- Kinsta renamed "PHP workers" to "PHP threads" across its platform in December 2024; both terms describe the same underlying PHP-FPM process.
- Redis object caching cuts database wait time enough that each worker finishes 2–5x faster, which raises effective site capacity without buying a bigger plan.
What Is a PHP Worker?
A PHP worker is an individual PHP-FPM process that receives one web request, executes your theme and plugin code against it, queries the database if needed, and returns a finished HTML response before picking up the next request. It's a single-threaded unit of work — one worker handles one request at a time, full stop, and cannot start a second job until the first finishes.
The name comes from PHP-FPM (FastCGI Process Manager), the standard way PHP runs behind Nginx or Apache on production servers. Every managed WordPress host — Kinsta, WP Engine, Cloudways, SiteGround — sizes its plans around how many of these processes run in parallel, because that number sets a hard ceiling on how much dynamic traffic your site can absorb at once. Static, cached traffic doesn't touch this ceiling at all, which is the part most explanations skip.
One naming wrinkle worth flagging up front: Kinsta renamed "PHP workers" to "PHP threads" across its docs, pricing pages, and dashboard in December 2024. Same mechanism, new label — this guide uses "worker" throughout since it's still the more common industry term, but don't be thrown off if you're reading Kinsta's own site and see "threads" instead.
Why PHP Worker Count Actually Matters
Here's the trap agencies fall into constantly: they treat worker count like a vanity metric on a pricing table, then get paged at 2am during a product launch because nobody modeled what happens when 40 people hit "Add to Cart" in the same 10 seconds. Worker exhaustion isn't a slow degradation — it's a cliff. Requests queue, then time out, then your checkout page starts throwing 504 Gateway Timeout errors while your homepage loads fine.
The mechanics are worth internalizing because they explain both failure modes and the fix. Object caching with Redis, for instance, doesn't add workers — it makes each one finish faster by pulling repeat database results from memory instead of re-querying MySQL. Sites that add Redis in front of a busy WooCommerce store commonly report database CPU load dropping 60–80% and time-to-first-byte on uncached pages falling from the 400–800ms range down under 200ms, which effectively multiplies how many concurrent users the same worker pool can carry. The pattern shows up repeatedly in client audits: the site wasn't under-resourced, it was doing 4x the database work it needed to per request.
The other practical reality is that hosts cap worker count by available RAM, not by CPU cores or some arbitrary tier gate. A typical WordPress PHP-FPM worker eats somewhere between 40MB and 80MB of memory in 2026 (more if you're running heavy image processing or a bloated page builder), so the math behind "you get 4 workers on this plan" is almost always available RAM ÷ average worker size, rounded down for safety margin.
The Anatomy of a WordPress Page Request
Before you can reason about capacity, you need to see what a single request actually does on the way through your server. WordPress isn't a folder of static HTML files — it's PHP code that assembles a page fresh from a MySQL database, and that assembly work is exactly what a worker does.
Here's the sequence for a standard, uncached request:
- Connection. A visitor's browser sends an HTTP request to your web server (Nginx or Apache), carrying headers, cookies, and user-agent data.
- Hand-off. The web server sees the request needs dynamic PHP execution and passes it to PHP-FPM over a Unix socket or local TCP connection.
- Worker assignment. PHP-FPM pulls one PHP worker from its pool and assigns it to this request. That worker is now busy and unavailable for anything else.
- Execution and queries. The worker runs your theme and plugin code, hitting MySQL for post content, meta fields, and user data as needed.
- HTML compilation. Once the database responds, the worker assembles the final HTML — stylesheets, scripts, and content all combined into one output.
- Response and release. The finished HTML goes back through the web server to the visitor's browser. The worker releases itself back to the pool, free to take the next request.
On a well-tuned server, this entire loop finishes in 100–200 milliseconds. But for that fraction of a second, the worker is 100% committed to that one request — it can't touch anything else. This is the number that matters most for capacity planning: cut your average execution time from 1,000ms to 100ms and the same worker pool now handles roughly 10x the requests per minute. Execution speed, not worker count, is usually the cheaper lever to pull first.
Cached vs. Uncached Requests: The Real Scaling Lever
The single biggest thing people misunderstand about PHP workers is this: a cached page request never touches PHP-FPM at all, so it never consumes a worker. When a caching layer — a plugin like WP Rocket, or server-level Nginx FastCGI caching like Kinsta runs by default — has already saved the compiled HTML for a page, the web server just reads that file straight off disk or RAM and serves it. No PHP execution, no database query, no worker occupied.
That's why a site running on just 2 workers can comfortably serve 100,000+ visits a day if 99% of that traffic is people reading cached blog posts or landing pages. The web server handles it directly. The equation flips hard, though, the moment your site has meaningful uncacheable traffic — anything that has to show a specific user something specific to them, in real time.
Common uncacheable actions include:
- Adding a product to a cart or completing a WooCommerce checkout
- Logging into a membership site or loading a personalized dashboard
- Submitting a contact form or posting a comment
- Running an on-site search query
- Background AJAX calls (chat widgets, heartbeat checks, live notifications)
Every one of those requires a worker, every single time. If a site has 2 workers and 3 people click "Add to Cart" in the same instant, the first two occupy both workers immediately; the third sits in a queue. If neither active worker frees up within a few seconds, that queued request times out and the visitor sees a 504 error. This is precisely why worker count, not raw traffic volume, is the number that decides whether your checkout survives a promotion.
Which Plugins Eat the Most PHP Workers
Not all plugins carry equal weight. Some run constant background processes that quietly keep workers occupied even when nobody's actively browsing. If you're seeing worker exhaustion warnings, these are the usual suspects:
Broken link checkers. These crawl your entire site and every outbound link on a recurring schedule, generating a steady stream of uncacheable PHP execution that has nothing to do with actual visitor traffic.
Live chat widgets. Any chat tool polling your database every few seconds for new messages is firing AJAX requests continuously — each one grabs a worker, however briefly.
On-site analytics plugins. Tools that log visitor stats directly into your WordPress database write a new row on every page view, which adds database write locks on top of the PHP overhead.
Heavy visual page builders. Builders that fire dozens or hundreds of individual queries just to render one page multiply the execution time of whatever worker picks up that request.
Query Monitor is the standard tool for finding these — it shows exact query counts and execution time per hook, so you can see which plugin is the actual offender rather than guessing.
How PHP-FPM Decides How Many Workers to Run
The available pool of workers on any server is governed by PHP-FPM's process manager configuration, and it runs in one of three modes. This part hasn't changed meaningfully in years, and it's still accurate for PHP 8.4 and 8.5 in 2026 — the FPM security patches this year (a May 2026 round addressing an XSS issue in FPM's request handling, alongside SOAP fixes) touched the request layer, not the process-manager mechanics below.
Static. PHP-FPM keeps a fixed number of workers running at all times, set by pm.max_children. Fastest option since there's no spin-up delay for new processes, but it holds that RAM continuously whether traffic is there or not. Best fit for high-traffic sites on dedicated resources.
Dynamic. PHP-FPM scales the active worker count with traffic, using pm.start_servers, pm.min_spare_servers, and pm.max_spare_servers alongside the max_children ceiling. This is the default most managed hosts run because it balances memory use against responsiveness.
On-demand. Workers spawn only when a request arrives and get killed once it's done. Lowest idle memory footprint, but each cold-start adds latency — a reasonable trade for low-traffic sites or admin-only backends, a bad one for anything customer-facing at volume.
The math behind pm.max_children is straightforward: available RAM for PHP-FPM divided by average worker size, rounded down for a safety buffer. On a server with 2GB allotted to PHP-FPM and workers averaging 80MB each, the safe ceiling is around 25 — go past that and you risk out-of-memory crashes during a traffic spike, not a graceful slowdown. It's also worth tuning pm.max_requests, which recycles a worker process after a set number of requests to clear out memory leaks before they compound into a crash.
Reading Your PHP-FPM Logs
You don't have to guess whether you're worker-constrained — the logs tell you directly. The warning to watch for looks like this:
[WARNING] pool www: server reached max_children setting (20), consider raising it
That line means every one of your 20 allocated workers was occupied simultaneously and new requests were queuing behind them. To check your own logs, SSH in and tail the file:
tail -n 100 /var/log/php-fpm.log
or, depending on your PHP version and distro:
tail -n 100 /var/log/php/php8.3-fpm.log
If that warning shows up repeatedly during specific windows — say, every morning at 9am when your email newsletter drives traffic — that's your signal to either speed up execution (object caching, plugin cleanup) or move up a hosting tier. Also worth watching: the slowlog, which records any script exceeding a set threshold (5 seconds is a common default) along with the exact file and line causing the delay — useful for pointing straight at a single misconfigured API call inside a booking plugin instead of guessing.
How Many PHP Workers Does Your Site Actually Need?
Use this as a starting baseline, then adjust up if your logs show queuing during real traffic:
| Site type | Typical traffic pattern | PHP workers needed |
|---|---|---|
| Blogs, brochure sites, portfolios | Near-100% cached; occasional contact form or admin login | 2 |
| Small WooCommerce (under 50 products), low-traffic membership sites | Regular but low-concurrency uncacheable requests | 4 |
| Active WooCommerce stores, LMS platforms, forums with live dashboards | Hundreds of uncacheable actions per hour | 6–8 |
| Marketplaces, ticket/event booking, flash-sale retail | Bursts of concurrent checkouts during promotions | 10–14+ |
If your traffic doesn't fit neatly into one row — a content site that also runs a small shop, say — size for your busiest uncacheable window, not your daily average. A blog with a checkout page open twice a week during a launch still needs enough workers to survive that launch window without queuing.
How to Reduce PHP Worker Usage Before You Upgrade
Buying more workers is the easy fix. It's usually not the cheapest one. Speeding up execution time gets you the same effective capacity increase without a plan upgrade, and it's worth doing first:
Add object caching (Redis or Memcached). This stores repeat database query results in memory so PHP doesn't re-query MySQL for the same product price or user meta on every load. On busy WooCommerce sites, this alone commonly cuts execution time enough to double or triple effective throughput per worker — aim for a Redis cache hit ratio above 80% once it's warmed up as your sign it's actually working.
Cut dead plugin weight. Every active plugin loads and executes on every relevant page view. Audit for "always-on" plugins — real-time link checkers, chat widgets polling constantly, stats loggers — and remove or replace the ones doing more database work than their value justifies.
Tame the WordPress Heartbeat API. Heartbeat fires AJAX calls from the admin dashboard every 15–60 seconds to check for autosaves and concurrent edits. Each call grabs a worker. A plugin like Heartbeat Control lets you throttle or disable it outside active editing sessions.
Offload search to an external service. WordPress's built-in search is database-heavy by default. If search traffic is significant, routing it through Algolia or ElasticPress takes that load off your PHP workers entirely.
None of these are exotic — they're the first four things worth checking on any client site reporting random slowness under load, in roughly that order, before ever recommending a plan upgrade.
Where Hosting Architecture Comes In
Worker count on a pricing page only tells half the story — the other half is what happens to your allocation when a neighboring site on shared infrastructure has a bad day. This is the "noisy neighbor" problem: on some hosting setups, one tenant's traffic spike or runaway plugin can starve CPU and memory for everyone sharing that server, regardless of how many workers your plan technically includes.
Kinsta runs each site in its own isolated LXD container — a dedicated slice of CPU and RAM that isn't shared with other customers' sites — which is the architectural reason a stated worker count on Kinsta tends to hold up under real load rather than degrading when someone else's site spikes. If you're evaluating hosts specifically because worker exhaustion has bitten you before, container isolation is worth weighing alongside the raw number, not instead of it. See the full plan lineup, pricing, and how its container model holds up under real traffic in the Kinsta review for the longer breakdown.
Frequently Asked Questions
How many PHP workers do I need for WooCommerce?
Most small-to-medium WooCommerce stores run comfortably on 4–6 workers, since checkout, cart, and account pages are all uncacheable by nature. Stores running flash sales or expecting concurrent checkout bursts should plan for 8–14+ workers to avoid 504 errors during peak minutes.
Does adding more PHP workers make my site load faster?
Not for an individual visitor, no. More workers increase how many simultaneous uncached requests your server can handle without queuing — they don't speed up any single page's execution time. If pages are slow one at a time, the fix is reducing execution time (caching, leaner plugins), not adding workers.
What's the difference between PHP workers and PHP threads?
Nothing functionally — they're the same PHP-FPM process. Kinsta renamed "PHP workers" to "PHP threads" across its platform in December 2024 to align with more common industry phrasing; other hosts, including WP Engine and Cloudways, still use "workers." Expect to see both terms depending on which host's docs you're reading.
Can I check how many PHP workers my current host gives me?
Yes — your hosting plan's documentation or dashboard usually states it directly (Kinsta, WP Engine, and Cloudways all list it per plan). You can also confirm actual usage by checking your PHP-FPM status page, if your host exposes one, or by tailing your PHP-FPM error log for max_children warnings.
Why does my site crash during traffic spikes even with caching enabled?
Page caching only protects static, publicly-shared content. If your spike involves logged-in users, cart activity, form submissions, or search queries, none of that is cacheable, so it all still competes for your fixed worker pool. A caching plugin won't save you during a sale — worker headroom and execution speed will.
What happens when all my PHP workers are busy?
Additional requests queue briefly, waiting for a worker to free up. If one becomes available within a few seconds, the visitor sees a slight delay. If the queue doesn't clear in time, the request times out and the visitor gets a 504 Gateway Timeout error instead of a page.
Final Thoughts
PHP workers are the resource that decides whether your site survives its busiest five minutes, not its average day. Caching protects you from volume; workers protect you from concurrency, and those are genuinely different problems that need different fixes. Get the execution time down first — Redis, a plugin audit, killing the Heartbeat spam — and you'll often find you didn't need the upgrade you were about to buy. When you do need more headroom, the worker number on the pricing page is only half the picture; ask how isolated that allocation actually is under someone else's bad day, too.
Swapan Kumar MannaThis is a verified profile
Product & Marketing Strategy Leader | AI & SaaS Growth Expert
With over 14 years of hands-on experience scaling 20+ B2B companies, I help founders bridge the gap between complex technology and sustainable business growth. As the Founder & CEO of Oneskai, my expertise spans Agentic AI enablement, software evaluation, and data-driven growth systems. Every guide, review, and strategy I share is rooted in real-world implementation, rigorous testing, and a commitment to objective, actionable insights.
