A WooCommerce store can serve cached browsing pages quickly while carts and checkout begin to queue. More visitors do not translate directly into a particular vCPU or RAM requirement: request mix, cache misses, payment calls, database work and background jobs determine the load. Capacity planning starts by measuring those separate demands.
This guide explains how to estimate vCPU, RAM and storage needs, then test the estimate before a campaign. The numerical examples are hypothetical planning calculations, not customer benchmarks or guaranteed package capacities. The objective is predictable checkout and sufficient operating margin under the store’s real traffic pattern.
What Capacity Planning Really Means for a WooCommerce Store
Capacity planning sounds like spreadsheets and stress, but at its heart it’s a conversation: what kind of traffic do you expect, how does your store behave under that traffic, and where will things bottleneck first? Start with three questions. First, how many PHP requests can you run at the same time without stepping on each other? That’s where vCPU plays the hero. Second, how big is each request in memory and how much space do your caches need to stay efficient? That’s RAM, your pantry. Third, how quickly can you read and write data, especially when orders and stock updates are flying? That’s your storage, measured by IOPS and throughput—the runway your planes need to take off and land safely.
WooCommerce traffic is not necessarily evenly distributed. Cached browsing can be light and bursty. Search can be spiky. Checkout is sensitive to delays because it involves more moving parts: payment gateway APIs, stock locks and order writes. Then there are imports, exports, image generation, scheduled tasks and webhooks. Planning only for browsing can underestimate checkout demand; there is no universal number of simultaneous shoppers at which checkout becomes overloaded. Planning only for sustained peak checkout load can also overstate everyday requirements. Match the measured traffic mix and campaign peaks to a setup with sufficient operating margin.
Think of your server like a restaurant kitchen. CPUs are cooks, and each PHP request is a dish. RAM is the fridge and pantry—it decides whether ingredients are nearby or whether cooks run to the storage room every time. IOPS and disk throughput are your delivery ramp and cash register—if they slow down, everything queues. A balanced kitchen is the goal. Too many cooks and too little fridge? Chaos. A giant pantry but no cooks? Still chaos. Balance wins.
How to Size vCPU for WooCommerce: It’s All About Concurrency
Adding vCPUs only helps when available CPU is a limiting factor. A store waiting on a payment API, a database lock or a saturated storage volume may gain little from that change. Compare per-route response times with CPU demand, FPM queues and dependency timings before buying more resources.
The human way to think about vCPU
Separate active visitors, request arrival rate and requests occupying PHP workers. A visitor can pause without using a worker, while a page may launch multiple API calls. Under stable unsaturated load, average busy workers are approximately origin dynamic requests/second × average worker service time. Exclude time queued before a worker starts. This is an average occupancy estimate, not the final max_children setting.
Estimate PHP CPU demand separately: dynamic requests/second × CPU seconds/request ÷ target utilization. For example, 20 requests/s × 0.08 CPU seconds ÷ 0.70 gives about 2.3 core equivalents for PHP. These are illustrative inputs, excluding colocated MySQL and background tasks. Hardware generation, shared vCPU scheduling, quotas and throttling affect actual capacity; validate on the intended plan. There is no universal requests-per-vCPU ratio.
PHP-FPM max_children caps simultaneous requests served by a pool. Too few workers can queue requests; too many can exhaust memory, overwhelm database connections or increase CPU contention and errors. Set the cap from measured memory, CPU, downstream limits and acceptable queueing. Test burst behavior and p95/p99 latency rather than setting the cap equal to average concurrency.
OPcache stores compiled PHP bytecode, reducing repeated compilation. A persistent object cache can avoid some repeated database reads when the application uses it effectively. They address different work, and neither guarantees a fixed CPU reduction. Measure OPcache hits/restarts, object-cache hits/evictions and the resulting route timings.
Don’t forget the non-PHP CPU users
Reserve capacity for measured database queries, cache processing, scheduled actions, imports, image work and backups. MySQL can consume CPU even when data is in memory, so cache hit rate alone does not establish its CPU budget. The required reserve varies by workload; one fixed spare vCPU is not a general rule.
RAM: The Pantry That Keeps Everything Within Arm’s Reach
RAM is where capacity planning gets pleasantly predictable. If CPU is how many things you can cook at once, RAM is whether the ingredients are within reach. WooCommerce loves memory for three reasons: PHP workers, database caches, and object caching.
Estimating memory per PHP worker
Measure worker memory during representative checkout, search and admin tasks. A hypothetical 16 workers at 150 MiB of private memory each use about 2,400 MiB, before shared OPcache and other services. Summed RSS may count shared pages repeatedly; use private/proportional measurements where available and validate total pool usage. PHP memory_limit is not an exact worker RSS reading. Allow for the distribution and heavy requests instead of using only a quiet-page average.
MySQL’s buffer pool and friends
Size the InnoDB buffer pool against the working set and observed reads while leaving room for connections, temporary operations and other database memory. A larger buffer pool can reduce disk reads, but cannot fix poor queries, locks or external waits. On a shared application/database host, allocating all spare RAM to MySQL can starve PHP or the OS. Validate total memory pressure and response times after changes.
Redis and object cache save you twice
A persistent object cache can reduce repeated database reads where keys are reused. Redis Object Cache is a third-party plugin listed in the WordPress directory, not an official core WordPress plugin. Check compatibility, hit rate, latency and memory behavior. Installing it does not automatically move WooCommerce’s authoritative session storage into Redis. A separate session backend needs its own durability, eviction and cart-correctness design.
For example, an 8 GiB host might experience pressure when checkout workers grow at the same time as database and Redis usage. Determine which allocations are actually useful before changing them. Redis evictions are normal for some cache workloads; high churn with poor hit rates warrants investigation. Do not use a disposable-cache eviction policy for authoritative session or queue data. Include shared memory, allocator overhead and background jobs in the host budget.
IOPS and Throughput: The Silent Deal-Breaker During Checkout
Let’s talk storage—the quiet hero that gets blamed last but fails first during big moments. IOPS (input/output operations per second) and throughput (how much data you can move) matter most when orders fly: order creation, stock updates, and sessions. If those writes block, everything queues. You can have plenty of CPU and RAM, but if your disk is doing a slow shuffle, users wait.
What actually hits the disk in WooCommerce?
Browse requests read data; carts and checkout can write sessions, orders, stock and logs. High-Performance Order Storage (HPOS) uses dedicated order tables and indexes and can reduce some order-query overhead. Check extension compatibility, synchronization/migration state and actual performance before switching an existing store. HPOS does not eliminate every database bottleneck or make unrelated product queries faster automatically.
Durable transaction commits depend on log writes and flushes. The InnoDB flush-at-commit setting changes crash-loss behavior; relaxing it for speed can lose acknowledged transactions. Consider sync_binlog and the storage stack too. Group commit means orders, SQL writes and physical IOPS are not one-to-one. Measure synchronous-write latency without casually trading away order durability.
Why NVMe helps, even when you don’t think you need it
NVMe can provide low-latency small I/O, but the label alone does not establish sustained checkout performance. Provider quotas, shared storage, queue depth, block size, read/write mix and durable flush behavior matter. Compare IOPS, throughput and latency under representative load. A database lock or slow payment response will not be repaired merely by replacing an SSD.
Binlogs, backups, and surprise I/O
There’s also the background noise: binary logs, slow query logs, backup jobs writing snapshot files, and image generation. These aren’t evil, but they will steal IOPS during peak if they run at the wrong time. I always recommend scheduling heavy jobs outside your peak window and ensuring backups are designed with load in mind. If you want a friendly primer on safer backup planning, this guide is a great starting point: The 3-2-1 Backup Strategy, Explained Like a Friend. The gist: backups are essential, but you don’t want them elbowing your customers off the dance floor.
Putting It Together: A Simple Sizing Playbook
Begin with the traffic distribution: origin request rates for browsing, search, cart, checkout and scheduled actions; cache-hit rates; and the size and duration of campaign bursts. Record response-time and error targets for each critical flow. Visitor counts alone are insufficient to calculate worker or CPU demand.
From there, we picture the shape of the stack:
First, calculate average worker occupancy from arrival rate and service time, then CPU demand from actual CPU time. Test the burst margin, database capacity and FPM queue. A request served entirely by a CDN/page cache may never need a PHP worker; do not count it as PHP work simply because a visitor loaded a page.
Second, budget peak worker private memory plus shared OPcache, total database memory, Redis overhead, other services and OS room. More cache is useful only while it improves hits without creating memory pressure. Monitor available memory, OOM events and active swap-in/out; old pages sitting in swap alone are not proof of current overload.
Third, measure storage at the actual mix of reads, writes and commits. Investigate quotas, queueing and DB waits before selecting faster storage or another volume. Separate volumes may still share a physical or provider limit. Schedule heavy jobs away from peaks where possible while preserving backup and log-archive recovery objectives.
A realistic example
For a hypothetical store receiving 20 dynamic requests/s with 0.5-second average worker service time, average occupancy is 10 workers. At 0.08 CPU seconds/request, PHP uses 1.6 core equivalents before headroom; a 70% utilization target gives about 2.3. Neither average alone selects the final server. Add database/jobs, measure tail latency and bursts, and cap workers within the memory and connection budget.
Caching Isn’t Cheating
If you want performance without sky-high bills, smart caching is your best friend. Page caching, object caching, and CDN caching can turn a roaring crowd into a gentle hum. But WooCommerce is tricky—cache the wrong things and you’ll break carts. That’s why I always say: cache hard where it’s safe, bypass where it’s personal.
The WordPress CDN caching guide explains public HTML and WooCommerce exclusions. Only share inspected non-personalized product/category responses; member pricing, currency and location may require variants or bypass. Exclude real cart/account/checkout routes, session/action/API requests and personal headers/cookies. Test cold-cache and purge conditions as well as steady hits.
The PHP-FPM, OPcache, Redis and MySQL tuning guide covers the separate roles of these components. Apply changes against a baseline and repeat the same workload; enabling a cache does not establish a particular percentage improvement.
Forecast Like a Pro
Use a production-like isolated test with representative data, plugins and cache rules. Model browsing, search, carts and checkout with separate sessions and realistic pacing. Use test payment services and prevent real emails, stock changes or other external side effects. Correlate route timings with FPM, CPU, memory, storage, DB locks and payment calls rather than diagnosing from one symptom.
Measure offered load as well as completed requests. A closed virtual-user test sends less new work when responses slow, potentially hiding a growing arrival-rate problem. An appropriate arrival-rate scenario can test campaign demand; also track dropped iterations and load-generator limits. Success includes correct carts, orders and retry behavior, not only low latency.
Run the expected CDN/cache policy, then test cold cache, controlled purges and personalized bypass. Define an acceptable degraded load or a waiting-room strategy instead of assuming the origin can survive only warm-cache conditions. Test duration and frequency should capture the relevant bursts, queue buildup and background jobs; twenty minutes once a quarter is not a universal standard.
The Little Things That Make a Big Difference
Validate HPOS compatibility and synchronization before rollout. For payment webhooks, use provider-supported authentication, idempotency and bounded retry handling; tune rate limits so valid callbacks succeed without removing protections wholesale. Reduce unnecessary debug noise while preserving payment, error and audit evidence. Queue delay can affect order completion even when page timings appear normal.
Image generation is a classic “who invited you?” during sales. If you bulk-upload or regenerate thumbnails while checkout is busy, the extra work can increase storage latency. Schedule that for quiet times. Same for heavy analytics exports. And plugin updates? Try not to roll them into traffic spikes, even if it’s “just a tiny fix.” Tiny fixes have a way of touching slow code paths you don’t expect.
Use slow-query evidence and execution plans to investigate scans, lock contention and indexing. A useful index can reduce scanned rows, but every added index consumes space and adds write maintenance. Test index changes, migrations and lock impact on staging; “add an index” is not a universal way to reduce write I/O.
Planning for Uptime and Graceful Failure
Not every performance story is about going faster. Sometimes it’s about how you fail. If a component slows down, does your store go down entirely, or does it degrade gracefully? Can customers still browse if the checkout stutters? Can you put up a “holding” message for a minute while you relieve pressure?
Anycast DNS and failover planning can improve reachability, but DNS/edge redundancy does not replicate orders or sessions. Checkout availability also requires a healthy target, consistent state, payment retry handling and a tested failover/cutover plan. Existing DNS caches can delay a switch.
Your Rule-of-Thumb Cheat Sheet (No Math Degree Required)
Let’s boil it down to a few practical, memory-friendly heuristics you can adjust for your reality:
For vCPU, measure dynamic request rate and CPU seconds per request, leaving measured room for the database and jobs. For workers, use service time, queueing and downstream limits. A pool of waiting requests is different from the same number of CPU-bound requests; tune against the actual mix.
For RAM, account for heavy worker requests, shared OPcache, all database allocations, Redis overhead and OS needs. Validate aggregate memory and active pressure. Allocate cache where observed reuse justifies it; extra configured cache can harm performance if it forces other services into swap or OOM.
For storage, size against checkout bursts and durable-write latency, not just average browsing IOPS. Correlate spikes with queries, locks, backups and provider limits before upgrading. Keep recovery objectives intact when moving background work to another time.
Comparing Two Hypothetical Scaling Choices
Imagine two stores whose checkout delays coincide with disk waits. One adds CPU without changing the storage path; the other first verifies the waits, then tests query improvements, useful cache and faster durable storage. The second approach targets the measured constraint, but no specific outcome follows until both are tested. If the real delay is a payment API, neither hardware change may help.
Resource balance means following the evidence: reduce avoidable work, verify where requests wait, and add capacity to the constrained component. Hardware and cache are options, not substitutes for route-level measurements.
Practical Setup Notes You Can Use Tomorrow
If you’re itching to tweak things today, here’s what I’d do in a calm afternoon:
Measure how much RAM your PHP workers use during a real checkout. Do a few test orders with coupons, multiple items, and shipping calculations. Note the peak memory. Set PHP-FPM max_children so you don’t oversubscribe RAM.
Set the MySQL buffer pool from measured working-set reuse within the full host memory budget. Include connection and temporary-operation memory, and verify that reducing reads does not create pressure elsewhere.
Enable a compatible object cache where repeated reads justify it, and measure hits, evictions and Redis latency. Size OPcache independently and inspect its memory/restart statistics. Keep authoritative sessions and queues out of an unexamined disposable-cache policy.
Review disk latency, quotas and DB waits during checkout. Test storage changes when they address the bottleneck. Preserve the store’s required transaction durability; changing flush or binlog settings is a data-loss decision, not a routine tuning shortcut.
Get your CDN and cache rules right for WooCommerce’s dynamic pages. If you want a friendly checklist for the sticky parts (like bypass rules for cart and checkout), this guide has you covered: CDN Caching Rules for WordPress.
Finally, keep a copy of your setup and your configuration notes somewhere safe. Backups aren’t just files—they’re confidence. If you’ve never set up a simple, automated plan, here’s a warm, practical walkthrough: The 3-2-1 Backup Strategy, Explained Like a Friend.
Signs You’re Undersized (and What to Nudge First)
Low CPU with slow pages can indicate FPM queueing, DB locks, storage or external-service waits. High CPU can indicate heavy code, queries or contention. Memory spikes need correlation with worker counts, cache churn, active swapping and OOM events. Use per-route traces and synchronized metrics to distinguish these causes; a single symptom does not identify the required upgrade.
During a slowdown, inspect the slow transaction end to end: web/FPM queue, PHP execution, database and external calls. Compare against the baseline and check errors and completed orders. Let the evidence choose the next change, then repeat the same test to confirm improvement.
Scaling Up Without Drama
Vertical scaling adds capacity to the existing host; horizontal designs separate responsibilities or add application instances. WooCommerce does not automatically route reads to replicas, and replica lag can break read-after-write assumptions for carts, orders and stock. Multi-node operation needs deliberate database routing, shared session/media handling, scheduled-job ownership and tested consistency. Optimize measured waste before increasing architectural complexity.
And if high availability is part of your roadmap, don’t leave it for last. Make a lightweight plan for how you’d fail over, how DNS would behave, and what “degraded mode” looks like. For a practical introduction, see How Anycast DNS and Automatic Failover Keep Your Site Up When Everything Else Goes Sideways.
Wrap-up: Your Store, Your Shape, Your Plan
Every store has a different mix of cached browsing, search, checkout and scheduled work. Capacity planning matches measured demand and service targets to vCPU, RAM and storage while accounting for cache misses, dependency delays and growth. There is no universal hardware package for a visitor count.
Start with how peak traffic really arrives. Size vCPU from dynamic request rate and measured CPU seconds per request, leaving room for MySQL and background jobs. Estimate PHP worker occupancy separately from worker service time, then test queueing and burst margin. Give RAM to the places that give back—PHP workers, buffer pool and Redis—within the full host budget. Measure storage demand and durable-write latency during checkout. Then rehearse the shopping flows and verify latency, errors and order correctness before going live.
Most of all, don’t chase numbers for their own sake. Chase smooth. Chase predictability. When the big day arrives and your store just hums along, you’ll know you sized it right. Hope this was helpful! See you in the next post—and if you want a deeper dive on server-side tuning for WordPress, keep this on your reading list: The Server-Side Secrets That Make WordPress Fly.





