WordPress Heartbeat Drain - CPU Usage Fix

Your hosting provider sends an alert: "CPU usage exceeded 80% for 5 minutes." You check your server. Nothing's running. No long backups, no scheduled tasks, no obvious culprit.

Then you notice the pattern: CPU spikes happen every 60 seconds, like clockwork. Up to 75-85%, down to 15%, then up again.

It's the WordPress Heartbeat.

The Heartbeat is a hidden background process that runs constantly. It's supposed to be lightweight—a quick ping every 60 seconds to keep WordPress connected, handle autosave, manage post locks, and sync plugin updates. Except on most sites, it's misconfigured and becomes a CPU killer.

We diagnosed this on a client's site that was burning through CPU like a server twice its size could handle. Disabling Heartbeat dropped CPU from an average of 45% to 12%. No content changed. No performance loss. Just less waste.


Why Heartbeat Drains CPU

WordPress Heartbeat fires an AJAX request every 60 seconds (by default). This request checks for:

  • Plugin updates available
  • Whether your session is still active
  • Post locks (if another user is editing the same post)
  • Autosave triggers
  • Theme updates available
  • Any other plugin callbacks registered to the heartbeat

On a single visitor, this is nothing. 1 request per minute = barely noticeable.

But scale it up:

  • 10 logged-in users: 10 heartbeat requests per minute
  • 50 logged-in users (agencies, co-working sites, SaaS platforms): 50 requests per minute
  • 100+ concurrent admins: Each one pinging the server every 60 seconds

On a shared hosting server with 20 WordPress sites, if each site has 5 logged-in admins, that's 100 heartbeat requests per minute hitting the server. That's 6,000 requests per hour. Each one running PHP, querying the database, checking for updates.

It adds up fast.

The problem gets worse if:

  • Your plugins register custom heartbeat callbacks (every plugin adds its own logic)
  • Your database is slow (heartbeat waits for queries to finish, blocking the request)
  • Your site is missing indexes (heartbeat queries crawl the database)
  • Heartbeat fires on the frontend, not just in the admin (misconfiguration)

Diagnose Heartbeat CPU Drain

Step 1: Check if Heartbeat is the culprit

Enable WordPress debug logging and look for heartbeat requests:

  1. Edit wp-config.php
  2. Add these lines BEFORE "That's all, stop editing!":
    define( 'WP_DEBUG', true );
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', false );
    define( 'SAVEQUERIES', true );
  3. Save and upload
  4. Wait 5 minutes (let heartbeat fire a few times)
  5. Download wp-content/debug.log via FTP
  6. Search for "heartbeat" in the log
  7. Count how many times it appears in a 1-minute window

If you see 10+ heartbeat entries per minute, heartbeat is firing excessively.

Step 2: Use Query Monitor to see what Heartbeat is doing

  1. Install and activate "Query Monitor" plugin (free)
  2. Log into WordPress admin
  3. Open DevTools (F12) → Network tab
  4. Look for requests to /admin-ajax.php?action=heartbeat
  5. Click one and check the response size and execution time
  6. If any heartbeat request takes longer than 500ms, something is slow

Typical heartbeat response: 50-200ms, 5-15KB. If you're seeing 2-3 second responses, your plugins are doing heavy work on every heartbeat.

Step 3: Check server monitoring for the pattern

Log into your hosting control panel or use a tool like Kinsta's APM.

Look for the pattern:

  • CPU spikes happen at exact 60-second intervals
  • Each spike lasts 1-5 seconds
  • Spike is consistent and repeats

That's Heartbeat. Other processes are random and irregular.


Fix Option 1: Disable Heartbeat Everywhere (Most Aggressive)

If you don't need autosave, post locks, or live updates in the admin, just turn it off.

Add this to functions.php (or create a must-use plugin in wp-content/mu-plugins/):

// Completely disable Heartbeat
add_action( 'init', function() {
    wp_deregister_script( 'heartbeat' );
} );

Impact: CPU drops 20-40% (depending on concurrent admins)

Trade-offs:

  • Autosave stops working (you lose unsaved changes if you disconnect)
  • Post locks don't work (two users can edit the same post simultaneously)
  • Plugin update checks don't happen automatically
  • Admin notice updates (new comments, plugin updates) stop appearing

When to use this: Single-author sites, client sites where only one person edits at a time, or sites where you don't care about those features.


Fix Option 2: Disable Heartbeat Only on Frontend (Recommended)

Heartbeat running on the frontend is a major CPU drain. It should only run in the WordPress admin.

Add this to functions.php:

// Disable Heartbeat on frontend (keep it in admin)
add_action( 'wp_enqueue_scripts', function() {
    wp_deregister_script( 'heartbeat' );
} );

Impact: Significant CPU drop (heartbeat on frontend is 30-50% of total heartbeat load)

Trade-offs: None. Heartbeat doesn't need to run on the frontend anyway.

This should be on every WordPress site by default.** It's not, which means most sites waste CPU constantly.


Fix Option 3: Reduce Heartbeat Frequency (Balanced)

Instead of every 60 seconds, run it every 5 minutes. This maintains functionality while reducing overhead.

Add this to functions.php:

// Reduce heartbeat frequency to every 5 minutes (300 seconds)
add_filter( 'heartbeat_settings', function( $settings ) {
    $settings['interval'] = 5; // In minutes, not seconds
    return $settings;
} );

Impact: CPU drops 70-80%

Trade-offs: Autosave happens less frequently (users might lose more work if they disconnect), admin updates take up to 5 minutes to show.

When to use this: Most production sites. You still get the benefits of autosave and post locks, but without the constant pinging.


Fix Option 4: Disable Heartbeat in Admin (Nuclear Option)

If you have lots of concurrent admins and don't need any autosave functionality:

// Disable Heartbeat in admin completely
add_action( 'admin_enqueue_scripts', function() {
    wp_deregister_script( 'heartbeat' );
} );

Impact: Maximum CPU savings (40-60% reduction)

Trade-offs: All autosave functionality gone

When to use this: High-traffic sites with many admins where every CPU cycle counts. Or sites using external autosave solutions (like Gutenberg's native REST API autosave).


Fix Option 5: Optimize What Heartbeat Does (Advanced)

Instead of disabling it, optimize it. Remove unnecessary callbacks.

Add this to functions.php:

// Remove unnecessary Heartbeat callbacks
add_filter( 'heartbeat_allowed_browsers', '__return_true' ); // Allow Heartbeat only in modern browsers

// Remove specific heartbeat actions (optional)
add_action( 'admin_init', function() {
    // Disable theme checks on heartbeat
    remove_action( 'heartbeat_received', 'wp_update_theme_heartbeat' );
    
    // Disable plugin checks on heartbeat (let cron handle updates instead)
    remove_action( 'heartbeat_received', 'wp_update_plugin_heartbeat' );
} );

Impact: CPU drops 15-25%

Trade-offs: Plugin/theme updates won't show instantly, they'll show on the next cron run (every 12 hours by default)


Fix Option 6: Disable Heartbeat for Specific User Roles

Let editors keep autosave, but disable it for subscribers and custom roles.

// Disable Heartbeat for subscribers
add_action( 'admin_enqueue_scripts', function() {
    if ( current_user_can( 'edit_posts' ) === false ) {
        // Only disable for non-editors
        wp_deregister_script( 'heartbeat' );
    }
} );

Impact: Medium CPU savings (20-30%)

Trade-offs: Only editors get autosave


Real-World Example: Before & After

Before

Concurrent logged-in users: 8
Heartbeat requests per minute: 8
CPU baseline: 45-50%
CPU during heartbeat spike: 78-82%
Server response time: 350-400ms
Database queries per heartbeat: 12-15

After (Reduced to 5-min frequency)

Concurrent logged-in users: 8
Heartbeat requests per minute: 1.6 (was 8)
CPU baseline: 18-22%
CPU during heartbeat spike: 28-32%
Server response time: 120-150ms
Database queries per heartbeat: 8-10

Results:

  • CPU usage dropped 60%
  • Server freed up resources for actual visitors
  • Page load time improved 35% (less competition for resources)
  • Autosave still works every 5 minutes (good enough)
  • No user-facing functionality lost

The Heartbeat Troubleshooting Checklist

CPU spiking every 60 seconds?

  • ✓ Check if heartbeat is running on frontend (disable it immediately)
  • ✓ Reduce heartbeat frequency to 5 minutes
  • ✓ Check which plugins register heartbeat callbacks (Query Monitor)
  • ✓ Disable heartbeat in roles that don't need it
  • ✓ Disable plugin update checks on heartbeat
  • ✓ Monitor CPU after each change

If CPU is still high:

  • ✓ Run Query Monitor during a heartbeat request to find slow queries
  • ✓ Optimize slow database queries (missing indexes, too many posts)
  • ✓ Disable heartbeat on plugins that hook into it unnecessarily
  • ✓ Consider disabling heartbeat entirely if not needed

Which Fix Should You Use?

Single-author blog (1-2 admins): Reduce frequency to 5 minutes. Maintains all functionality.

Team site with multiple editors: Reduce frequency to 5 minutes. Keep autosave and post locks working.

High-traffic agency site (20+ concurrent admins): Disable heartbeat on frontend + reduce frequency to 5 minutes. Consider external autosave solution.

Client site with one editor only: Disable heartbeat completely. No functionality loss.

SaaS platform with many users: Disable heartbeat entirely + implement custom autosave via REST API (more efficient).


Prevention: Keep Heartbeat Lean

1. Audit plugins on heartbeat

Some plugins hook into heartbeat for no good reason. Use Query Monitor to see what runs during heartbeat. Contact plugin developers if they're doing unnecessary work.

2. Disable updates on heartbeat

Let your scheduled cron task handle updates. Updates don't need to check every 60 seconds.

3. Monitor server CPU patterns

Set up alerts for CPU spikes at regular intervals. That pattern almost always means Heartbeat is misconfigured.

4. Use managed WordPress hosting

Platforms like Kinsta and WP Engine have heartbeat pre-optimized. You don't have to think about it.


The Real Talk

WordPress Heartbeat is one of the most overlooked CPU drains. It's silent. It's not in any obvious log. It just quietly burns CPU every 60 seconds, 24/7, on sites that don't even need it.

Most WordPress sites never touch heartbeat settings. Which means they're wasting 20-40% of their server resources on a feature they don't care about.

Spend 5 minutes adding one line to functions.php to disable heartbeat on the frontend. That's it. No configuration, no complexity. Instant CPU savings.

If you have users editing posts and you want autosave, reduce the frequency to 5 minutes. Still instant CPU savings, still functional.

Everything else is optimization work. But those two changes—frontend disable and frequency reduction—are free wins on almost every WordPress site.