When a site gets sluggish at odd hours, most owners start deactivating plugins at random and hope the graph goes down. Learning how to debug high CPU usage on your WordPress server works better in the opposite order: measure first, identify the process that is actually burning cycles, then change one thing. This guide walks through the triage sequence we use on real production sites, from load average to the request that started it all.
What “High CPU Usage” Actually Means on a WordPress Server
CPU usage on its own is a poor alarm. A server pegged at 95% for eight seconds while it regenerates a cache is healthy, while a server sitting at 60% for six hours is usually a sign that something is looping.
The number that matters more is load average relative to core count. On a 4-core box, a load average of 4.0 means the CPU is fully committed with nothing queued; 12.0 means requests are waiting three deep and visitors are feeling it.
The second number is PHP workers. Each uncached request occupies one worker until it finishes, so a plan with 4 workers and a 2-second average response time tops out near 120 requests per minute before queuing begins. High CPU and worker exhaustion usually appear together.
The 15-Minute Triage: Find the Process Before You Blame a Plugin
- Check load average per core. Run uptime or htop and compare the 1, 5 and 15-minute figures. A high 1-minute value with a low 15-minute value is a spike; three high values is a sustained problem.
- Identify the guilty process. Sort by CPU in htop. PHP-FPM children point at application code, mysqld points at queries, and an unfamiliar binary running as the web user points at malware.
- Map the worker to a URL. Enable the PHP-FPM status page or run ps aux | grep php-fpm while the load is high. You are looking for the script path, which is nearly always index.php, admin-ajax.php or wp-cron.php.
- Correlate with traffic. Count requests per minute in the access log for that same window and see whether real visitors, a crawler, or a single IP caused it.
- Only then touch a plugin. With a URL and a timestamp, you can usually name the plugin in one query instead of ten deactivations.
Read the Logs in the Right Order
Logs answer the question “what was the server doing at 03:14” better than any dashboard. Pull the same five-minute window from each source and line them up.
- Access log: count hits per IP and per URL. awk ‘{print $1}’ access.log | sort | uniq -c | sort -rn | head -20 exposes scrapers in seconds.
- PHP error log: repeated fatal errors and warnings inflate CPU because every failed request still costs a full bootstrap.
- MySQL slow query log: set long_query_time to 1 second temporarily. Queries against wp_options with autoload data, or wp_postmeta without an index, are the usual repeat offenders.
- PHP-FPM slow log: it prints a stack trace for any request over your threshold, which names the exact plugin function that hung.
The Five Culprits Behind Most WordPress CPU Spikes
After enough incidents, the pattern list gets short. In our experience these five account for the large majority of WordPress high CPU usage tickets.
For a closer look at this topic, see our guide: GZIP vs. Brotli Compression: Which is Better for WordPress?.
- Uncached bot traffic. AI crawlers, price scrapers and vulnerability scanners hit uncacheable URLs (search pages, faceted filters, ?add-to-cart) and each one costs a full PHP execution. This is also why raw bandwidth numbers mislead people, a point we cover in the truth about unlimited bandwidth.
- WP-Cron pileups. Because WordPress fires cron on page loads, a busy site can trigger overlapping jobs. The official WP-Cron documentation recommends disabling the loopback and running a real system cron every 5 minutes instead.
- admin-ajax.php and the Heartbeat API. Open admin tabs poll every 15 to 60 seconds. Ten editors plus a page builder can generate more backend load than the public site.
- index.php running heavy queries. WordPress index.php high CPU usage almost always traces to an uncached query loop: related posts, filtered archives, or a shortcode running WP_Query without limits.
- Malware. Spam mailers, cryptominers and doorway page generators run constantly. Scan your WordPress site for malware if CPU stays higher with near-zero traffic, and follow the WordPress hacked site checklist before restoring anything.
How to Fix High CPU Usage Once You Know the Cause
Each cause has a matching fix, and the order below moves from cheapest to most involved.
- Serve more requests from cache. Full-page caching at the server level takes PHP out of the path entirely. Sites moving from a plugin-only cache to server-level caching commonly drop CPU by 60% to 80% on read-heavy pages.
- Add object caching. Redis or Memcached stores query results between requests, which cuts database CPU on dynamic pages. Our breakdown of Redis versus Memcached covers when each makes sense.
- Upgrade PHP. Modern versions execute the same code with measurably fewer cycles, which is why we treat PHP 8.3 and newer as the baseline rather than an option.
- Rate-limit and filter bots. Block bad user agents at the edge, add crawl-delay rules, and keep search and filter URLs out of the crawlable index.
- Fix the query, not the symptom. Add the missing index, clear autoloaded options above 1 MB, and cap WP_Query loops with posts_per_page and no_found_rows.
Monitor So the Next Spike Is Boring
Reactive debugging is expensive because the evidence disappears when the load drops. Keep 30 days of per-minute CPU, memory and PHP worker metrics, and set an alert on sustained CPU above 80% for 10 minutes rather than on instant peaks.
Pair that with weekly slow query reviews and a synthetic uptime check. Hosts that surface this data in the dashboard, as we do for business WordPress hosting accounts, save you from SSH archaeology at midnight. Resource-hungry setups like LMS and course sites benefit most, since logged-in traffic bypasses page cache by design.
Frequently Asked Questions
How to check what is causing high CPU usage?
Run htop or top and sort by CPU to name the process within 60 seconds, then map that process to a URL using the PHP-FPM status page or slow log. From there, cross-reference your access log for the same timestamp to see which requests, IPs or crawlers triggered the work.
How to resolve 100% CPU usage?
Stabilise first by blocking the top offending IP or user agent and disabling WP-Cron loopbacks, which typically drops load within 2 to 5 minutes. Then apply the durable fix: full-page caching, an object cache, a PHP upgrade, or the missing database index that the slow query log identified.
Why is 90% of my CPU being used?
Sustained 90% usage on a WordPress server usually means a high share of requests are bypassing cache, most often from bots, logged-in sessions, or admin-ajax polling. If traffic is low and CPU stays at 90%, scan for malware, because cryptominers and spam mailers run continuously regardless of visitors.
Is 95% CPU usage normal?
Short bursts to 95% are normal and even efficient, since idle CPU is wasted capacity. It becomes a problem when the 15-minute load average exceeds your core count or response times climb past 800 ms, which signals requests are queuing rather than executing.
Want the CPU graph to stay flat?
If you would rather spend your evenings writing than reading slow logs, our managed platform handles server-level caching, PHP tuning and worker scaling for you. Talk to a WordPress specialist at WebVibo about a free migration and we will benchmark your current CPU load first.
[…] Related reading: How to Debug High CPU Usage on Your WordPress Server. […]
[…] 9 or higher on dynamic output. If your load average climbs after enabling compression, our guide on how to debug high CPU usage on your WordPress server walks through isolating the […]
[…] load is climbing and you’re not sure why, our walkthrough on debugging high CPU usage on a WordPress server covers the log queries and process checks we run during incidents. Version-controlled configs help […]