If your CPU graph looks like an actual heartbeat monitor — regular spikes every 15 to 60 seconds, even when nobody's supposedly doing anything — there's a good chance the culprit is WordPress itself, not a hacked plugin or a traffic spike. It's called the Heartbeat API, and on busy multi-author sites or resource-capped shared hosting, it can quietly eat more CPU than everything else on the page combined.

Symptom: Rhythmic CPU Spikes and a Sluggish wp-admin

A few tells that point straight at Heartbeat rather than a generic performance problem:

  • Your VPS monitoring or cPanel resource graph shows short, evenly-spaced CPU spikes, often every 15–60 seconds, that don't line up with any visitor traffic pattern.
  • The front end of the site is fine, but wp-admin gets noticeably slower the longer you leave a browser tab open on the Dashboard, Post Editor, or Plugins page.
  • Your access or error logs show a flood of POST /wp-admin/admin-ajax.php requests, often dozens per minute from just one or two logged-in editors.
  • On shared cPanel hosting, you're hitting 508 Resource Limit Is Reached or getting LVE throttling warnings even though your traffic hasn't changed.
  • It gets dramatically worse when several people have the editor open in another browser tab and just leave it there.

If you want to confirm it before changing anything, open your browser's Network tab (F12) while sitting on any wp-admin screen and watch for repeated admin-ajax.php calls with action=heartbeat in the POST payload. That's your smoking gun.

Cause: WordPress Is Polling Your Server on a Timer

The Heartbeat API is a built-in WordPress feature (since 3.6) that uses admin-ajax.php to send a small AJAX request to the server on a regular interval, purely so the browser and server can stay in sync. It's what powers:

  • The “someone else is editing this post” lock warning.
  • Session expiration and auto-logout warnings.
  • Autosave in the block editor.
  • Live post-status and plugin activity updates on the Dashboard, such as WooCommerce order counts.

By default it fires roughly every 15–60 seconds per open admin tab, per logged-in user. That sounds trivial — and on a beefy VPS with two admins, it usually is. The problem is what each of those requests actually costs. admin-ajax.php loads the entire WordPress bootstrap: wp-load.php, every active plugin, the full init hook chain, and often a handful of database queries, just to answer whether anyone is still there. Multiply that by five editors with the post editor open in a background tab all day, or a WooCommerce store with an admin dashboard left open on a shop-floor screen, and you've got a background PHP process running near-continuously.

On CloudLinux and cPanel accounts with CPU or entry-process limits, this is exactly the kind of steady drip that eats your LVE quota without ever showing up as a single obvious spike. It's death by a thousand small requests.

Fix 1: Confirm It's Actually Heartbeat Before Changing Anything

Don't skip this step, since treating every CPU spike as a Heartbeat problem wastes time when the real cause is a crawler or a slow query. On a VPS, tail your access log while someone has wp-admin open in another tab:

tail -f /var/log/nginx/access.log | grep admin-ajax

If you see a steady stream of hits with no other activity happening, that's Heartbeat. If the requests correlate with real visitor traffic instead, look elsewhere and start with general CPU troubleshooting steps for slow WordPress sites.

Fix 2: Control the Interval Instead of Killing It Outright

The cleanest fix is a small plugin purpose-built for this: Heartbeat Control (free, by WP Rocket) or Perfmatters if you already use it for other performance tweaks. Both let you, per-location:

LocationRecommended setting
Dashboard (wp-admin home)Slow to 60–120 seconds, or disable if nobody needs live widgets
Post editorKeep enabled since autosave and lock warnings depend on it, but set to 60 seconds
Front endDisable entirely, since almost no theme needs Heartbeat for visitors

This gets you most of the CPU savings while keeping autosave and the editing-lock warning working, which matters when more than one person edits content.

Fix 3: Manual Control via a Code Snippet (No Plugin)

If you'd rather not add another plugin, you can throttle the interval with a filter in your theme's functions.php or a small custom plugin:

add_filter( 'heartbeat_settings', function( $settings ) {
    $settings['interval'] = 60; // seconds, minimum allowed is 15
    return $settings;
} );

To kill it completely on the front end only, which is safe for almost every site:

add_action( 'init', function() {
    if ( ! is_admin() ) {
        wp_deregister_script( 'heartbeat' );
    }
} );

Avoid disabling Heartbeat globally with remove_action('init', 'wp_heartbeat_actions') unless you're certain no plugin on the site depends on it. WooCommerce, several page builders, and some security plugins use Heartbeat for their own live checks, and you'll break those features silently.

Fix 4: Address the Root Cause on Multi-Editor Sites

If you've got a newsroom-style site with many logged-in authors, the real fix is behavioral as much as technical: ask editors to close the post editor tab when they're not actively writing, rather than leaving several drafts open across the day. Combine that with the interval throttling above and the CPU pattern usually flattens out within a day.

Prevention

  • Install Heartbeat Control, or set the filter above, on every new WordPress build as a standard step rather than as a reaction to a resource warning.
  • On shared cPanel hosting, check your account's CPU and entry-process usage in cPanel's Resource Usage screen periodically. A slow creeping baseline, rather than a sharp spike, is the classic Heartbeat signature and is easy to miss until you get throttled.
  • If you run a WooCommerce store, keep Heartbeat enabled on the Orders screen since it drives live order notifications, but throttle it everywhere else rather than disabling it store-wide by reflex.
  • Revisit the setting after any major plugin update. Some plugins reset Heartbeat-related options or add their own polling that stacks on top of core's.

Frequently Asked Questions

Will disabling Heartbeat break autosave in the post editor?

Only if you disable it specifically in the post editor location. Autosave and the editing-lock warning both depend on Heartbeat while you're inside the editor, so throttle the interval there instead of turning it off completely.

Is Heartbeat the same thing as WP-Cron?

No. WP-Cron handles scheduled tasks like publishing timed posts and plugin maintenance jobs, and it fires on page loads rather than a live timer. Heartbeat is a real-time AJAX poll tied to open browser tabs. They're unrelated causes that happen to produce similar-looking symptoms, so don't assume fixing one fixes the other.

I disabled Heartbeat everywhere and my WooCommerce dashboard stopped updating live. Why?

WooCommerce uses Heartbeat for live stock and order count updates on the Dashboard and Orders screen. If you disabled it globally rather than by location, that feature loses its data feed. Re-enable it for wp-admin specifically and throttle the interval instead of killing it outright.

How do I know if Heartbeat is actually a meaningful percentage of my CPU usage, versus just noise?

Watch admin-ajax.php hit frequency in your access logs against your total request count over the same window, or use top or htop on a VPS while a wp-admin tab sits open and idle for ten minutes. If PHP-FPM workers spin up repeatedly with no other activity happening, that idle baseline is your answer.

Does this affect shared cPanel hosting differently than a VPS?

Yes. On a VPS with spare capacity, unthrottled Heartbeat is often just wasted CPU cycles you never notice. On shared cPanel hosting with CloudLinux CPU and entry-process limits, that same steady drip can push you into throttling or a 508 error even at otherwise normal traffic levels, since your account has a hard ceiling rather than headroom to absorb it.