{"id":3125,"date":"2025-12-07T17:29:01","date_gmt":"2025-12-07T14:29:01","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/php-fpm-settings-for-wordpress-and-woocommerce-pm-pm-max_children-and-pm-max_requests\/"},"modified":"2025-12-07T17:29:01","modified_gmt":"2025-12-07T14:29:01","slug":"php-fpm-settings-for-wordpress-and-woocommerce-pm-pm-max_children-and-pm-max_requests","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/php-fpm-settings-for-wordpress-and-woocommerce-pm-pm-max_children-and-pm-max_requests\/","title":{"rendered":"PHP-FPM Settings for WordPress and WooCommerce: pm, pm.max_children and pm.max_requests"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>When a WordPress or WooCommerce site feels slow or starts throwing 502\/504 errors under load, we often find the root cause in one place: misconfigured PHP-FPM pools. The three settings that matter most are <strong>pm<\/strong>, <strong>pm.max_children<\/strong> and <strong>pm.max_requests<\/strong>. They decide how many PHP workers you really have, how much RAM those workers will eat, and how gracefully they recycle over time. In this article, we will walk through how we at dchost.com choose these values in real projects, from small blogs to busy WooCommerce stores.<\/p>\n<p>We will avoid vague advice like \u201cset it to 50\u201d and instead build a simple, repeatable way to size your PHP-FPM pools based on available RAM, process memory usage and expected concurrency. We will also show how tuning differs between a content site and a checkout-heavy WooCommerce store, and how to verify that your choices are actually working in production. By the end, you should be able to look at a server and say: \u201cthis is how many PHP workers it can safely run, and here is the config to match\u201d.<\/p>\n<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Why_PHP-FPM_Tuning_Matters_So_Much_for_WordPress_and_WooCommerce\"><span class=\"toc_number toc_depth_1\">1<\/span> Why PHP-FPM Tuning Matters So Much for WordPress and WooCommerce<\/a><\/li><li><a href=\"#Quick_Primer_How_PHP-FPM_Works\"><span class=\"toc_number toc_depth_1\">2<\/span> Quick Primer: How PHP-FPM Works<\/a><\/li><li><a href=\"#Understanding_pm_pmmax_children_and_pmmax_requests\"><span class=\"toc_number toc_depth_1\">3<\/span> Understanding pm, pm.max_children and pm.max_requests<\/a><ul><li><a href=\"#pm_Choosing_the_Process_Manager_Mode\"><span class=\"toc_number toc_depth_2\">3.1<\/span> pm: Choosing the Process Manager Mode<\/a><\/li><li><a href=\"#pmmax_children_How_Many_PHP_Workers_You_Really_Have\"><span class=\"toc_number toc_depth_2\">3.2<\/span> pm.max_children: How Many PHP Workers You Really Have<\/a><\/li><li><a href=\"#pmmax_requests_Recycling_Workers_to_Avoid_Memory_Leaks\"><span class=\"toc_number toc_depth_2\">3.3<\/span> pm.max_requests: Recycling Workers to Avoid Memory Leaks<\/a><\/li><\/ul><\/li><li><a href=\"#The_Core_Formula_How_to_Size_pmmax_children_Safely\"><span class=\"toc_number toc_depth_1\">4<\/span> The Core Formula: How to Size pm.max_children Safely<\/a><ul><li><a href=\"#Step_1_Measure_Average_PHP-FPM_Process_Memory\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Step 1: Measure Average PHP-FPM Process Memory<\/a><\/li><li><a href=\"#Step_2_Decide_How_Much_RAM_You_Can_Give_to_PHP-FPM\"><span class=\"toc_number toc_depth_2\">4.2<\/span> Step 2: Decide How Much RAM You Can Give to PHP-FPM<\/a><\/li><li><a href=\"#Step_3_Compute_pmmax_children\"><span class=\"toc_number toc_depth_2\">4.3<\/span> Step 3: Compute pm.max_children<\/a><\/li><li><a href=\"#Example_1_Small_WordPress_Blog_on_2_GB_VPS\"><span class=\"toc_number toc_depth_2\">4.4<\/span> Example 1: Small WordPress Blog on 2 GB VPS<\/a><\/li><li><a href=\"#Example_2_Mid-Size_WooCommerce_Store_on_8_GB_NVMe_VPS\"><span class=\"toc_number toc_depth_2\">4.5<\/span> Example 2: Mid-Size WooCommerce Store on 8 GB NVMe VPS<\/a><\/li><li><a href=\"#Example_3_High-Traffic_WooCommerce_on_16_GB_Server\"><span class=\"toc_number toc_depth_2\">4.6<\/span> Example 3: High-Traffic WooCommerce on 16 GB Server<\/a><\/li><\/ul><\/li><li><a href=\"#Choosing_pm_pmmax_children_and_pmmax_requests_for_WordPress_vs_WooCommerce\"><span class=\"toc_number toc_depth_1\">5<\/span> Choosing pm, pm.max_children and pm.max_requests for WordPress vs WooCommerce<\/a><ul><li><a href=\"#WordPress_Blogs_and_Content_Sites\"><span class=\"toc_number toc_depth_2\">5.1<\/span> WordPress Blogs and Content Sites<\/a><\/li><li><a href=\"#WooCommerce_Stores\"><span class=\"toc_number toc_depth_2\">5.2<\/span> WooCommerce Stores<\/a><\/li><li><a href=\"#pmmax_requests_for_WordPress_and_WooCommerce\"><span class=\"toc_number toc_depth_2\">5.3<\/span> pm.max_requests for WordPress and WooCommerce<\/a><\/li><\/ul><\/li><li><a href=\"#Typical_PHP-FPM_Configs_for_Common_Hosting_Scenarios\"><span class=\"toc_number toc_depth_1\">6<\/span> Typical PHP-FPM Configs for Common Hosting Scenarios<\/a><ul><li><a href=\"#1_Shared_Hosting_with_Limited_Access\"><span class=\"toc_number toc_depth_2\">6.1<\/span> 1) Shared Hosting with Limited Access<\/a><\/li><li><a href=\"#2_Single_WordPress_Site_on_a_Small_VPS_24_GB\"><span class=\"toc_number toc_depth_2\">6.2<\/span> 2) Single WordPress Site on a Small VPS (2\u20134 GB)<\/a><\/li><li><a href=\"#3_Single_WooCommerce_Store_on_816_GB_VPS\"><span class=\"toc_number toc_depth_2\">6.3<\/span> 3) Single WooCommerce Store on 8\u201316 GB VPS<\/a><\/li><li><a href=\"#4_Multi-Site_Multi-Tenant_WordPress_on_One_Server\"><span class=\"toc_number toc_depth_2\">6.4<\/span> 4) Multi-Site \/ Multi-Tenant WordPress on One Server<\/a><\/li><\/ul><\/li><li><a href=\"#Monitoring_and_Iterative_Tuning_Did_You_Get_It_Right\"><span class=\"toc_number toc_depth_1\">7<\/span> Monitoring and Iterative Tuning: Did You Get It Right?<\/a><ul><li><a href=\"#Key_Things_to_Monitor\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Key Things to Monitor<\/a><\/li><li><a href=\"#Symptoms_and_How_to_Adjust\"><span class=\"toc_number toc_depth_2\">7.2<\/span> Symptoms and How to Adjust<\/a><\/li><\/ul><\/li><li><a href=\"#Putting_It_All_Together_A_Practical_Checklist\"><span class=\"toc_number toc_depth_1\">8<\/span> Putting It All Together: A Practical Checklist<\/a><\/li><li><a href=\"#Conclusion_A_Calm_Data-Driven_Way_to_Tune_PHP-FPM\"><span class=\"toc_number toc_depth_1\">9<\/span> Conclusion: A Calm, Data-Driven Way to Tune PHP-FPM<\/a><\/li><\/ul><\/div>\n<h2><span id=\"Why_PHP-FPM_Tuning_Matters_So_Much_for_WordPress_and_WooCommerce\">Why PHP-FPM Tuning Matters So Much for WordPress and WooCommerce<\/span><\/h2>\n<p>WordPress and WooCommerce are both PHP applications. Every uncached page view, AJAX request or admin action runs through PHP-FPM. If PHP-FPM is tuned too small, visitors queue for a free worker and your Time To First Byte (TTFB) rises. If it is tuned too large, workers fight for RAM, the server swaps, and everything becomes slow or unstable.<\/p>\n<p>Unlike simple static hosting, a dynamic site has three critical bottlenecks: CPU, RAM and the database. PHP-FPM sits in the middle, brokering every dynamic request to PHP code and MySQL. That is why we always tune PHP-FPM side by side with MySQL, caching and <a href='https:\/\/www.dchost.com\/blog\/en\/php-ayarlarini-dogru-yapmak-memory_limit-max_execution_time-ve-upload_max_filesize-kac-olmali\/'>core PHP ini settings like memory_limit and max_execution_time<\/a>. For WooCommerce, which has heavier queries and more authenticated traffic, the impact is even stronger.<\/p>\n<p>If you get PHP-FPM right, you usually see three immediate benefits:<\/p>\n<ul>\n<li>Lower median and p95 TTFB for uncached requests<\/li>\n<li>Far fewer 502\/504 gateway errors during traffic spikes<\/li>\n<li>Much more predictable CPU and RAM usage under load<\/li>\n<\/ul>\n<p>Let\u2019s start with a quick reminder of how PHP-FPM works under the hood.<\/p>\n<h2><span id=\"Quick_Primer_How_PHP-FPM_Works\">Quick Primer: How PHP-FPM Works<\/span><\/h2>\n<p>PHP-FPM (FastCGI Process Manager) is a daemon that keeps a pool of PHP worker processes ready to handle incoming requests from the web server (Nginx, Apache with proxy_fcgi, LiteSpeed, etc.). Each worker handles <strong>one request at a time<\/strong>. When the request is done, the worker becomes idle and waits for the next one.<\/p>\n<p>Key points to keep in mind:<\/p>\n<ul>\n<li>Each worker is a PHP process that consumes RAM. The more plugins and themes you load, the bigger each process becomes.<\/li>\n<li>Your effective concurrency is roughly \u201cnumber of workers\u201d per pool. 10 workers means at most 10 concurrent uncached PHP requests.<\/li>\n<li>Workers can be pre-spawned (ready ahead of time) or spawned on demand, depending on the <strong>pm<\/strong> mode.<\/li>\n<li>Workers are occasionally recycled to avoid memory leaks and long-living processes. This is what <strong>pm.max_requests<\/strong> is about.<\/li>\n<\/ul>\n<p>PHP-FPM settings live in pool config files, usually under <code>\/etc\/php-fpm.d\/<\/code> (RedHat\/AlmaLinux\/Rocky) or <code>\/etc\/php\/*\/fpm\/pool.d\/<\/code> (Debian\/Ubuntu). On many control panels, each site or account gets its own pool, which is ideal for isolation and per-site tuning. For a deeper, practical look at PHP-FPM itself, you can also read our article on <a href='https:\/\/www.dchost.com\/blog\/en\/wordpress-icin-sunucu-tarafi-optimizasyon-php-fpm-opcache-redis-ve-mysql-ile-neyi-ne-zaman-nasil-ayarlamalisin\/'>server-side secrets that make WordPress fly with PHP-FPM and OPcache<\/a>.<\/p>\n<h2><span id=\"Understanding_pm_pmmax_children_and_pmmax_requests\">Understanding pm, pm.max_children and pm.max_requests<\/span><\/h2>\n<h3><span id=\"pm_Choosing_the_Process_Manager_Mode\">pm: Choosing the Process Manager Mode<\/span><\/h3>\n<p>The <code>pm<\/code> setting controls <strong>how<\/strong> PHP-FPM manages worker processes. You will typically see one of three values:<\/p>\n<ul>\n<li><strong>pm = static<\/strong>: A fixed number of workers equal to <code>pm.max_children<\/code> are always kept running.<\/li>\n<li><strong>pm = dynamic<\/strong>: PHP-FPM keeps a minimum number of workers and scales up to <code>pm.max_children<\/code> as needed.<\/li>\n<li><strong>pm = ondemand<\/strong>: Workers are spawned when requests come in and killed after being idle for a while.<\/li>\n<\/ul>\n<p>How to choose for WordPress and WooCommerce:<\/p>\n<ul>\n<li><strong>dynamic<\/strong> \u2013 Our default for most WordPress and WooCommerce setups. It balances resource usage and responsiveness, especially under fluctuating load.<\/li>\n<li><strong>static<\/strong> \u2013 Good for very stable, high-traffic environments where you know exactly how many workers you need and want predictability over elasticity.<\/li>\n<li><strong>ondemand<\/strong> \u2013 Useful on very small <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a> or low-traffic sites to save RAM when there is no traffic, but it can hurt TTFB on the first request after idle periods.<\/li>\n<\/ul>\n<p>For typical WooCommerce stores on a VPS, we almost always start with <strong>pm = dynamic<\/strong>. On heavily optimized, high-traffic clusters, we sometimes use <strong>pm = static<\/strong> for tighter control.<\/p>\n<h3><span id=\"pmmax_children_How_Many_PHP_Workers_You_Really_Have\">pm.max_children: How Many PHP Workers You Really Have<\/span><\/h3>\n<p><code>pm.max_children<\/code> is the <strong>hard cap<\/strong> on how many PHP worker processes can exist in a pool at once. This number effectively defines your maximum concurrent PHP requests for that pool.<\/p>\n<p>If you set this number too low, requests line up waiting for a free worker, and you see increased response times and sometimes 502 errors from the web server (timeout while waiting for PHP). If you set it too high, workers consume more RAM than you actually have, the server starts swapping, and the entire box slows down or even becomes unstable.<\/p>\n<p>Getting <code>pm.max_children<\/code> right is mostly about RAM math: how big each worker is, and how much memory you can dedicate to PHP-FPM after accounting for MySQL, cache (Redis\/Memcached), the OS and other services.<\/p>\n<h3><span id=\"pmmax_requests_Recycling_Workers_to_Avoid_Memory_Leaks\">pm.max_requests: Recycling Workers to Avoid Memory Leaks<\/span><\/h3>\n<p><code>pm.max_requests<\/code> tells PHP-FPM how many requests a single worker will handle before it is gracefully restarted. After serving that many requests, PHP-FPM kills the worker and spawns a new one. This helps:<\/p>\n<ul>\n<li>Mitigate memory leaks in PHP, extensions or plugins<\/li>\n<li>Keep long-living processes from growing too large over time<\/li>\n<li>Refresh APCu\/OPcache in some edge cases (though OPcache has its own policies)<\/li>\n<\/ul>\n<p>If <code>pm.max_requests<\/code> is set too <strong>low<\/strong>, workers get recycled too often, adding overhead and occasionally causing short CPU spikes. If it is set too <strong>high<\/strong> or left unlimited, memory usage can creep up over days until you suddenly hit swap or OOM kills.<\/p>\n<p>For WordPress\/WooCommerce, we typically start with values between <strong>300 and 1,000<\/strong>. Heavier stores with many plugins often benefit from a slightly lower value to keep leaks in check, while simple blogs can afford a higher one.<\/p>\n<h2><span id=\"The_Core_Formula_How_to_Size_pmmax_children_Safely\">The Core Formula: How to Size pm.max_children Safely<\/span><\/h2>\n<p>Let\u2019s build a simple formula you can reuse on any server. The basic idea is:<\/p>\n<p><strong>maximum PHP workers \u2248 available RAM for PHP \/ average RAM per PHP process<\/strong><\/p>\n<p>We will refine this with safety margins, but that is the foundation.<\/p>\n<h3><span id=\"Step_1_Measure_Average_PHP-FPM_Process_Memory\">Step 1: Measure Average PHP-FPM Process Memory<\/span><\/h3>\n<p>You cannot guess this accurately; plugins and themes change everything. Measure it on your own site under realistic load. On a Linux VPS or <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a>, run (adjust PHP version\/pool name as needed):<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">ps -o rss,cmd -C php-fpm | grep 'pool=www'<\/code><\/pre>\n<p><code>rss<\/code> is resident set size in KB. You can also use <code>top<\/code> or <code>htop<\/code> and look at PHP-FPM processes during a period of active traffic: browse the site, run a few WooCommerce checkouts, open wp-admin, etc.<\/p>\n<p>Example: you observe several PHP-FPM workers using between 120 MB and 180 MB RSS. You can take <strong>160 MB<\/strong> as a conservative average. In KB that is about 160,000, but for easier math we will keep values in MB.<\/p>\n<h3><span id=\"Step_2_Decide_How_Much_RAM_You_Can_Give_to_PHP-FPM\">Step 2: Decide How Much RAM You Can Give to PHP-FPM<\/span><\/h3>\n<p>Your PHP-FPM pool does not own the whole server. On a box running WordPress\/WooCommerce you typically have:<\/p>\n<ul>\n<li>The OS and background services (SSH, systemd, etc.)<\/li>\n<li>Web server (Nginx\/Apache\/LiteSpeed)<\/li>\n<li>Database (MySQL\/MariaDB\/PostgreSQL)<\/li>\n<li>Cache layer (Redis\/Memcached), maybe Elasticsearch or OpenSearch<\/li>\n<li>Monitoring agents, backup agents, etc.<\/li>\n<\/ul>\n<p>On a dedicated WordPress\/WooCommerce server or NVMe VPS at dchost.com, a reasonable first approximation is:<\/p>\n<ul>\n<li>Reserve <strong>30\u201340%<\/strong> of total RAM for MySQL and caches<\/li>\n<li>Reserve <strong>10\u201320%<\/strong> for OS and web server<\/li>\n<li>Give the remaining <strong>40\u201360%<\/strong> to PHP-FPM<\/li>\n<\/ul>\n<p>On a small 4 GB VPS, for example, we might budget:<\/p>\n<ul>\n<li>1.2 GB for MySQL + Redis<\/li>\n<li>0.8 GB for OS + Nginx<\/li>\n<li>2.0 GB for PHP-FPM<\/li>\n<\/ul>\n<p>If you run multiple PHP pools (for multiple sites), that PHP budget must be split across them. Agencies hosting many WordPress sites on one stack often find our guide on <a href='https:\/\/www.dchost.com\/blog\/en\/ajanslar-ve-freelancerlar-icin-hosting-mimarisi-20-wordpress-sitesini-tek-altyapida-guvenle-yonetmek\/'>hosting architecture for agencies managing 20+ WordPress sites<\/a> useful here.<\/p>\n<h3><span id=\"Step_3_Compute_pmmax_children\">Step 3: Compute pm.max_children<\/span><\/h3>\n<p>Now we divide the PHP-FPM RAM budget by the average process size and add a safety margin:<\/p>\n<p><strong>pm.max_children = floor( PHP_RAM_budget_MB \/ avg_process_MB ) \u00d7 safety_factor<\/strong><\/p>\n<p>We usually use a <strong>safety_factor between 0.7 and 0.8<\/strong> to avoid edging too close to real limits (there are always spikes).<\/p>\n<h3><span id=\"Example_1_Small_WordPress_Blog_on_2_GB_VPS\">Example 1: Small WordPress Blog on 2 GB VPS<\/span><\/h3>\n<p>Suppose:<\/p>\n<ul>\n<li>Total RAM: 2 GB<\/li>\n<li>Average PHP worker RSS: 80 MB<\/li>\n<li>We allocate 900 MB to PHP-FPM<\/li>\n<\/ul>\n<p>Math:<\/p>\n<ul>\n<li>Raw max workers: 900 \/ 80 \u2248 11.25 \u2192 11<\/li>\n<li>With 0.8 safety factor: 11 \u00d7 0.8 \u2248 8.8 \u2192 <strong>8 workers<\/strong><\/li>\n<\/ul>\n<p>So we would set:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">pm = dynamic\npm.max_children = 8\npm.start_servers = 2\npm.min_spare_servers = 2\npm.max_spare_servers = 4\npm.max_requests = 500<\/code><\/pre>\n<p>For a low-traffic blog with good full-page caching, 8 workers is usually more than enough.<\/p>\n<h3><span id=\"Example_2_Mid-Size_WooCommerce_Store_on_8_GB_NVMe_VPS\">Example 2: Mid-Size WooCommerce Store on 8 GB NVMe VPS<\/span><\/h3>\n<p>Now consider a WooCommerce store using many plugins and a heavier theme:<\/p>\n<ul>\n<li>Total RAM: 8 GB<\/li>\n<li>Measured PHP worker RSS: 150\u2013220 MB \u2192 take 200 MB for safety<\/li>\n<li>We allocate 3.5 GB to PHP-FPM<\/li>\n<\/ul>\n<p>Math:<\/p>\n<ul>\n<li>Raw max workers: 3,500 \/ 200 = 17.5 \u2192 17<\/li>\n<li>Safety factor 0.75: 17 \u00d7 0.75 \u2248 12.75 \u2192 <strong>12 workers<\/strong><\/li>\n<\/ul>\n<p>Config could look like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">pm = dynamic\npm.max_children = 12\npm.start_servers = 4\npm.min_spare_servers = 4\npm.max_spare_servers = 8\npm.max_requests = 400<\/code><\/pre>\n<p>This gives you up to 12 concurrent PHP requests. Combined with aggressive full-page caching for anonymous traffic and object caching for logged-in users, this often comfortably handles a few hundred concurrent visitors with occasional checkout bursts. For capacity planning specifically for WooCommerce, we go into more detail in our guide on <a href='https:\/\/www.dchost.com\/blog\/en\/woocommerce-kapasite-planlama-rehberi-vcpu-ram-iops-nasil-hesaplanir\/'>WooCommerce capacity planning and sizing vCPU\/RAM\/IOPS<\/a>.<\/p>\n<h3><span id=\"Example_3_High-Traffic_WooCommerce_on_16_GB_Server\">Example 3: High-Traffic WooCommerce on 16 GB Server<\/span><\/h3>\n<p>On a busy store, maybe behind a CDN with well-tuned cache rules, you might see:<\/p>\n<ul>\n<li>Total RAM: 16 GB<\/li>\n<li>Average PHP worker RSS: 250 MB (large plugin stack, heavy theme)<\/li>\n<li>PHP-FPM budget: 7 GB<\/li>\n<\/ul>\n<p>Math:<\/p>\n<ul>\n<li>Raw workers: 7,000 \/ 250 = 28<\/li>\n<li>Safety 0.75: 28 \u00d7 0.75 = 21 \u2192 <strong>pm.max_children = 21<\/strong><\/li>\n<\/ul>\n<p>Config:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">pm = static\npm.max_children = 21\npm.max_requests = 500<\/code><\/pre>\n<p>Here we might choose <strong>pm = static<\/strong> because the store has very predictable high load and we want all 21 workers pre-warmed and ready. This is the sort of configuration we deploy on dedicated WooCommerce servers or higher-end VPS at dchost.com where we know the resource envelope very well.<\/p>\n<h2><span id=\"Choosing_pm_pmmax_children_and_pmmax_requests_for_WordPress_vs_WooCommerce\">Choosing pm, pm.max_children and pm.max_requests for WordPress vs WooCommerce<\/span><\/h2>\n<h3><span id=\"WordPress_Blogs_and_Content_Sites\">WordPress Blogs and Content Sites<\/span><\/h3>\n<p>A typical content site has:<\/p>\n<ul>\n<li>High ratio of anonymous traffic<\/li>\n<li>Effective full-page caching (Nginx microcaching, LiteSpeed Cache, or a CDN)<\/li>\n<li>Less complex plugins compared to an e-commerce stack<\/li>\n<\/ul>\n<p>This means most requests do not hit PHP at all if caching is well configured. For those that do, they are often relatively light. On these sites we often see smaller PHP workers (60\u2013120 MB) and can run more workers per GB of RAM.<\/p>\n<p>For a medium blog on a 4 GB VPS with good caching, a reasonable starting point might be:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">pm = dynamic\npm.max_children = 12\npm.start_servers = 3\npm.min_spare_servers = 3\npm.max_spare_servers = 6\npm.max_requests = 800<\/code><\/pre>\n<p>We also strongly recommend pairing this with good full-page caching. Our article on <a href='https:\/\/www.dchost.com\/blog\/en\/wordpress-icin-sunucu-tarafi-optimizasyon-php-fpm-opcache-redis-ve-mysql-ile-neyi-ne-zaman-nasil-ayarlamalisin\/'>server-side optimization for WordPress with PHP-FPM, OPcache, Redis and MySQL<\/a> shows how much relief caching can give your PHP workers.<\/p>\n<h3><span id=\"WooCommerce_Stores\">WooCommerce Stores<\/span><\/h3>\n<p>WooCommerce changes the picture in a few important ways:<\/p>\n<ul>\n<li>More authenticated traffic (logged-in customers and admins)<\/li>\n<li>Cart, checkout, My Account and admin are mostly <strong>uncacheable<\/strong> as full pages<\/li>\n<li>More plugins: payment gateways, shipping, marketing, reporting, etc.<\/li>\n<li>More AJAX (cart fragments, live search, shipping calculators)<\/li>\n<\/ul>\n<p>All of this increases average request cost and inflates PHP worker memory usage. It also means that even with aggressive HTML caching for product\/category pages, you must size PHP-FPM for checkout peaks.<\/p>\n<p>For a small WooCommerce store on a 4 GB VPS, we might start with something like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">pm = dynamic\npm.max_children = 8\npm.start_servers = 3\npm.min_spare_servers = 3\npm.max_spare_servers = 6\npm.max_requests = 300<\/code><\/pre>\n<p>On a bigger 8\u201316 GB server hosting a single store, 12\u201324 workers is common, as in the earlier examples. Just remember that increasing <code>pm.max_children<\/code> increases RAM usage nearly linearly, so you must re-check memory consumption after changes.<\/p>\n<h3><span id=\"pmmax_requests_for_WordPress_and_WooCommerce\">pm.max_requests for WordPress and WooCommerce<\/span><\/h3>\n<p>We almost never leave <code>pm.max_requests<\/code> at the default of 0 (unlimited). Over days or weeks, you commonly see PHP workers grow in RSS as they handle more complex requests. A moderate recycle limit keeps things in check without causing churn.<\/p>\n<p>Typical ranges we use in real projects:<\/p>\n<ul>\n<li>Small WordPress site: <strong>pm.max_requests = 800\u20131,000<\/strong><\/li>\n<li>Medium content or light WooCommerce: <strong>500\u2013800<\/strong><\/li>\n<li>Heavy WooCommerce with many plugins: <strong>300\u2013500<\/strong><\/li>\n<\/ul>\n<p>If you notice that PHP-FPM memory usage keeps creeping up over time (e.g., every day RSS grows by a few hundred MB), try lowering <code>pm.max_requests<\/code> a bit and monitor again.<\/p>\n<h2><span id=\"Typical_PHP-FPM_Configs_for_Common_Hosting_Scenarios\">Typical PHP-FPM Configs for Common Hosting Scenarios<\/span><\/h2>\n<h3><span id=\"1_Shared_Hosting_with_Limited_Access\">1) Shared Hosting with Limited Access<\/span><\/h3>\n<p>On shared hosting, you often do not have direct control over <code>pm<\/code> settings; the provider sets global limits for all accounts. In that situation, your main levers are:<\/p>\n<ul>\n<li>Optimizing <code>memory_limit<\/code> and other PHP ini values (see our detailed guide on <a href='https:\/\/www.dchost.com\/blog\/en\/php-ayarlarini-dogru-yapmak-memory_limit-max_execution_time-ve-upload_max_filesize-kac-olmali\/'>choosing PHP memory_limit, max_execution_time and upload_max_filesize<\/a>)<\/li>\n<li>Using full-page caching (LiteSpeed Cache, Nginx-based cache, or a CDN)<\/li>\n<li>Reducing heavy plugins and simplifying the theme<\/li>\n<\/ul>\n<p>If you constantly hit resource limits on shared hosting, it might be time to move to a VPS where you can control PHP-FPM directly. We have a step-by-step checklist for a smooth transition in our article on <a href='https:\/\/www.dchost.com\/blog\/en\/paylasimli-hostingden-vpse-sorunsuz-gecis-rehberi\/'>moving from shared hosting to a VPS without downtime<\/a>.<\/p>\n<h3><span id=\"2_Single_WordPress_Site_on_a_Small_VPS_24_GB\">2) Single WordPress Site on a Small VPS (2\u20134 GB)<\/span><\/h3>\n<p>For a small business site or blog with moderate traffic on a 2\u20134 GB VPS, a good starting point is:<\/p>\n<ul>\n<li>Measure PHP worker RSS (typically 70\u2013120 MB)<\/li>\n<li>Allocate ~40\u201350% of RAM to PHP-FPM<\/li>\n<li>Use <strong>pm = dynamic<\/strong> with 6\u201312 workers<\/li>\n<\/ul>\n<p>Example for 4 GB RAM, 100 MB workers, 1.5 GB to PHP:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">pm = dynamic\npm.max_children = 10\npm.start_servers = 3\npm.min_spare_servers = 3\npm.max_spare_servers = 6\npm.max_requests = 800<\/code><\/pre>\n<p>Pair this with OPcache enabled (and sized reasonably), a caching plugin, and database tuning and you have a very capable small stack.<\/p>\n<h3><span id=\"3_Single_WooCommerce_Store_on_816_GB_VPS\">3) Single WooCommerce Store on 8\u201316 GB VPS<\/span><\/h3>\n<p>For a store that expects real-time traffic, carts and checkouts, we increase both the worker memory estimate and concurrency:<\/p>\n<ul>\n<li>Measure PHP worker RSS (often 150\u2013300 MB)<\/li>\n<li>Allocate 40\u201360% of RAM to PHP-FPM<\/li>\n<li>Target 12\u201324 workers, depending on RAM and concurrency needs<\/li>\n<\/ul>\n<p>Example for 8 GB RAM, 200 MB workers, 3.5 GB to PHP (as before):<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">pm = dynamic\npm.max_children = 12\npm.start_servers = 4\npm.min_spare_servers = 4\npm.max_spare_servers = 8\npm.max_requests = 400<\/code><\/pre>\n<p>If your store is growing fast, plan ahead not only for PHP-FPM but also for MySQL, Redis and potential future separation of roles. Our article on <a href='https:\/\/www.dchost.com\/blog\/en\/woocommerce-icin-ayri-veritabani-ve-onbellek-sunucusu-ne-zaman-mantikli\/'>when WooCommerce really needs separate database and cache servers<\/a> explains when this step becomes logical.<\/p>\n<h3><span id=\"4_Multi-Site_Multi-Tenant_WordPress_on_One_Server\">4) Multi-Site \/ Multi-Tenant WordPress on One Server<\/span><\/h3>\n<p>If you host several sites or a WordPress Multisite network on one VPS or dedicated server, you will typically have:<\/p>\n<ul>\n<li>One pool per site (stronger isolation, clearer metrics)<\/li>\n<li>Or one pool per cluster of similar sites (simpler config, less overhead)<\/li>\n<\/ul>\n<p>The formula is the same, but you now split the PHP RAM budget across pools. High-traffic or heavy WooCommerce pools get more workers; small brochure sites get fewer. On dchost.com multi-site stacks, we often allocate a base of 2\u20134 workers for tiny sites and 6\u201316 for primary sites.<\/p>\n<h2><span id=\"Monitoring_and_Iterative_Tuning_Did_You_Get_It_Right\">Monitoring and Iterative Tuning: Did You Get It Right?<\/span><\/h2>\n<p>PHP-FPM tuning is not a \u201cset once and forget forever\u201d task. Traffic, plugins and code change over time. You should validate your configuration and revisit it regularly, especially after major theme or plugin changes.<\/p>\n<h3><span id=\"Key_Things_to_Monitor\">Key Things to Monitor<\/span><\/h3>\n<ul>\n<li><strong>PHP-FPM status page<\/strong> (if enabled): see active processes, idle processes, max active, queue length.<\/li>\n<li><strong>Server RAM<\/strong>: watch for swap usage; if swap grows steadily, you are likely overcommitted.<\/li>\n<li><strong>CPU usage<\/strong>: consistently maxed-out CPU suggests either too many workers or very heavy code.<\/li>\n<li><strong>Web server logs<\/strong>: 502\/504 errors, upstream timeout errors, long request durations.<\/li>\n<li><strong>Access logs<\/strong>: burst patterns around campaigns, newsletters, or sales.<\/li>\n<\/ul>\n<p>Even simple tools like <code>top<\/code>, <code>htop<\/code>, <code>vmstat<\/code> and <code>journalctl -u php-fpm<\/code> tell you a lot. For a deeper view on diagnosing slow responses, including TTFB issues caused by PHP-FPM, check out our guide on <a href='https:\/\/www.dchost.com\/blog\/en\/yuksek-ttfb-sorununu-cozmek-wordpress-ve-php-sitelerde-sunucu-tarafli-nedenler-ve-cozumler\/'>fixing high TTFB on WordPress and PHP sites<\/a>.<\/p>\n<h3><span id=\"Symptoms_and_How_to_Adjust\">Symptoms and How to Adjust<\/span><\/h3>\n<p><strong>Symptom 1: High CPU, but low RAM, frequent 502\/504 under spike<\/strong><\/p>\n<ul>\n<li>Possible cause: too many workers, CPU saturated.<\/li>\n<li>Action: lower <code>pm.max_children<\/code> slightly; optimize slow queries and heavy plugins; ensure caching is doing its job.<\/li>\n<\/ul>\n<p><strong>Symptom 2: RAM constantly near 100%, swap used, system feels sluggish<\/strong><\/p>\n<ul>\n<li>Possible cause: too many workers or oversized <code>memory_limit<\/code>.<\/li>\n<li>Action: reduce <code>pm.max_children<\/code>, revisit <code>memory_limit<\/code>, reduce plugin bloat; consider upgrading to a plan with more RAM.<\/li>\n<\/ul>\n<p><strong>Symptom 3: Requests sometimes wait a long time before PHP starts processing<\/strong><\/p>\n<ul>\n<li>Possible cause: too few workers; PHP-FPM queue building up.<\/li>\n<li>Action: increase <code>pm.max_children<\/code> slightly if RAM allows; verify that caching is correct so you are not wasting workers on anonymous traffic.<\/li>\n<\/ul>\n<p><strong>Symptom 4: PHP-FPM memory usage grows day by day, then resets after reloads<\/strong><\/p>\n<ul>\n<li>Possible cause: memory leaks, too high or unlimited <code>pm.max_requests<\/code>.<\/li>\n<li>Action: reduce <code>pm.max_requests<\/code> in steps (e.g., 1,000 \u2192 600 \u2192 400), monitor again.<\/li>\n<\/ul>\n<h2><span id=\"Putting_It_All_Together_A_Practical_Checklist\">Putting It All Together: A Practical Checklist<\/span><\/h2>\n<p>To recap the process we follow for WordPress and WooCommerce sites on dchost.com infrastructure, here is a step-by-step checklist you can adapt:<\/p>\n<ol>\n<li><strong>Enable OPcache and caching<\/strong> (page cache + object cache) so PHP-FPM is not doing unnecessary work.<\/li>\n<li><strong>Measure average PHP worker RSS<\/strong> under realistic load using <code>ps<\/code>, <code>top<\/code> or <code>htop<\/code>.<\/li>\n<li><strong>Define a RAM budget for PHP-FPM<\/strong> after reserving memory for MySQL, caches, OS and other services.<\/li>\n<li><strong>Compute pm.max_children<\/strong> using the formula and add a safety factor of 0.7\u20130.8.<\/li>\n<li><strong>Pick pm mode<\/strong>: usually <code>pm = dynamic<\/code> for most sites; <code>static<\/code> for high-traffic, well-understood stores.<\/li>\n<li><strong>Set pm.max_requests<\/strong> in a moderate range (300\u20131,000) depending on complexity.<\/li>\n<li><strong>Reload PHP-FPM<\/strong>, monitor RAM\/CPU and access logs for a few days.<\/li>\n<li><strong>Iterate<\/strong>: adjust <code>pm.max_children<\/code> and <code>pm.max_requests<\/code> based on real data, not guesswork.<\/li>\n<\/ol>\n<p>As your traffic grows, plan capacity upgrades early instead of waiting for pain. That might mean scaling up to a larger VPS, moving to a dedicated server, or separating database and cache roles. Our articles on <a href='https:\/\/www.dchost.com\/blog\/en\/woocommerce-kapasite-planlama-rehberi-vcpu-ram-iops-nasil-hesaplanir\/'>WooCommerce capacity planning<\/a> and <a href='https:\/\/www.dchost.com\/blog\/en\/woocommerce-icin-ayri-veritabani-ve-onbellek-sunucusu-ne-zaman-mantikli\/'>when to split database and cache servers<\/a> can help you design that roadmap.<\/p>\n<h2><span id=\"Conclusion_A_Calm_Data-Driven_Way_to_Tune_PHP-FPM\">Conclusion: A Calm, Data-Driven Way to Tune PHP-FPM<\/span><\/h2>\n<p>Tuning PHP-FPM for WordPress and WooCommerce does not have to be mysterious. Once you understand what <strong>pm<\/strong>, <strong>pm.max_children<\/strong> and <strong>pm.max_requests<\/strong> actually do, the problem turns into straightforward capacity planning: measure how big each worker is, decide how much RAM you can safely spend, and let the math tell you how many workers you can run.<\/p>\n<p>From our experience managing WordPress and WooCommerce workloads on dchost.com servers, the biggest wins come from combining smart PHP-FPM settings with good caching, realistic PHP ini limits and a clean plugin stack. If you are constantly fighting resource limits on shared hosting, or if your WooCommerce checkout slows down during campaigns, it is probably time to look at both your PHP-FPM config and the underlying hosting resources.<\/p>\n<p>If you would like a hosting environment where you control PHP-FPM pools fully and have room to grow, our NVMe VPS, dedicated server and colocation options are designed with exactly these kinds of workloads in mind. Size your server realistically, apply the formulas from this guide, and keep an eye on real-world metrics. With that combination, PHP-FPM stops being a bottleneck and becomes a solid foundation your WordPress or WooCommerce site can grow on.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>When a WordPress or WooCommerce site feels slow or starts throwing 502\/504 errors under load, we often find the root cause in one place: misconfigured PHP-FPM pools. The three settings that matter most are pm, pm.max_children and pm.max_requests. They decide how many PHP workers you really have, how much RAM those workers will eat, and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3126,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-3125","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3125","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=3125"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3125\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/3126"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=3125"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=3125"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=3125"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}