1. Identify the Culprit: top and htop
Before changing WordPress settings, look at the OS level. Run htop (or top) via SSH to see which process is eating the cycles.
php-fpmis high: One of your plugins or your theme is running a heavy or infinite loop.mysqlis high: You have unindexed queries, or your database tables are fragmented.nginxis high: You are likely under a DDoS or a heavy bot scrape.
2. Disable the WP Heartbeat API
The Heartbeat API (admin-ajax.php) maintains a connection between the browser and the server while the dashboard is open. If you have multiple tabs open or multiple authors logged in, these “pulses” can consume massive CPU.
- The Fix: Use a snippet to throttle the pulse or disable it entirely on the frontend.
- Code: “`php add_action( ‘init’, ‘stop_heartbeat’, 1 ); function stop_heartbeat() { wp_deregister_script(‘heartbeat’); }
3. Replace WP-Cron with a System Cron
By default, WordPress checks for scheduled tasks every time a page is loaded. On high-traffic sites, this creates a massive, unnecessary CPU overhead.
- The Fix: Disable the virtual cron in
wp-config.php:define('DISABLE_WP_CRON', true); - The System Fix: Set up a real cron job in Linux (
crontab -e) to run every 5 minutes:*/5 * * * * curl -I https://yourdomain.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
4. Profile with Query Monitor or Xdebug
If php-fpm is the problem, you need to find the specific plugin causing the leak.
- Query Monitor: Install this to see which plugin is running the most database queries or taking the longest to load.
- The “Slow Log”: Enable the PHP-FPM slow log in your pool configuration (
www.conf) to capture scripts that take longer than 2 or 3 seconds to execute.
5. Offload Search and Background Tasks
WordPress’s native search uses LIKE queries in SQL, which are incredibly CPU-intensive on large databases.
- The Fix: If your site has thousands of posts, offload search to Elasticsearch or use a service like Algolia.
- Background Processing: For tasks like image optimization or data syncing, ensure they are handled by a background worker (like Action Scheduler) rather than during the page request cycle.