Performance

The WordPress Heartbeat API and admin-ajax.php: Taming Hidden Server Load

The WordPress Heartbeat API and admin-ajax.php: Taming Hidden Server Load

When a WordPress server shows high CPU usage even though traffic is modest, one of the first things I check is the access log for requests to admin-ajax.php. On some sites, it’s the most requested URL on the server, more than the homepage. Every one of those requests loads WordPress and runs PHP, and none of them can be page cached.

Often, a large share of these requests come from the Heartbeat API, a WordPress feature that sends regular background requests from the browser to the server. Heartbeat is useful, but on busy sites, or when many people leave admin tabs open, it can create significant hidden load. Plugins that use admin-ajax.php inefficiently make it worse.

Here’s how Heartbeat and admin-ajax work, how to find out whether they’re causing problems and how to control them safely.

What admin-ajax.php is

admin-ajax.php is WordPress’s traditional endpoint for AJAX requests, background requests from JavaScript to the server. Despite the “admin” in its name, it’s used on both the admin and the front end. Plugins use it for features like live search, cart updates, form submissions, filters and notifications.

Every request to admin-ajax.php loads the full WordPress environment, including all active plugins. That makes each request relatively expensive, and none of them can be served from a page cache.

What the Heartbeat API does

Heartbeat sends a request to admin-ajax.php at regular intervals while a WordPress page is open in the browser. WordPress and plugins use it for:

  • Autosaving posts while you edit.
  • Post locking, which warns you if someone else is editing the same post.
  • Session management, showing a login prompt if your session expires.
  • Real-time notifications in some plugins.
  • Dashboard updates in some plugins, like live statistics.

By default, Heartbeat runs every 15 seconds on the post editor and less frequently on other admin pages, roughly every 60 seconds. It slows down further when a browser tab is inactive. Some themes and plugins also enable it on the front end.

When Heartbeat becomes a problem

On a single-user blog, Heartbeat’s load is negligible. It becomes noticeable when:

  • Many editors or staff keep admin tabs open all day. Ten people with five tabs each means dozens of requests per minute, all day.
  • Store staff leave WooCommerce admin pages open while processing orders.
  • Plugins attach heavy work to Heartbeat requests, running database queries or external API calls on every beat.
  • Hosting has limited PHP workers, so Heartbeat requests compete with real visitors.
  • Heartbeat runs on the front end for every visitor.

On shared hosting, heavy admin-ajax usage can also trigger resource limit warnings or suspensions.

Step 1: Find out what’s happening

Check the access log

Count requests to admin-ajax.php and compare them with other traffic:

awk '{print $7}' access.logsortuniq -csort -rnhead</code>

Heartbeat requests are POST requests. The action parameter is in the request body, so it doesn’t appear in standard access logs. To see which AJAX actions are being called, use browser developer tools on pages that are open, or a monitoring plugin that logs AJAX actions.

Use browser developer tools

Open an admin page, open the network tab and filter by admin-ajax. Watch requests appear at regular intervals. Click a request and look at the payload to see the action, such as heartbeat, and the response, which shows what plugins sent back.

Use Query Monitor

Query Monitor can show details about AJAX requests, including database queries and time spent, helping identify plugins that do heavy work on each request.

Step 2: Adjust Heartbeat carefully

You can control Heartbeat with the heartbeat_settings filter and by deregistering the script where it isn’t needed. The goal is reducing unnecessary requests while keeping features that matter.

Slow it down in the admin

Increasing the interval reduces requests significantly:

WordPress limits the allowed range for the interval. A value around 60 seconds is a common compromise that greatly reduces load.

Keep it in the post editor

Autosave and post locking depend on Heartbeat. Disabling it in the editor risks lost work and editors overwriting each other’s changes. If you change behaviour in the editor, slow it modestly rather than disabling it.

Disable it on the front end

For most sites, Heartbeat isn’t needed on the front end. If a theme or plugin loads it there, you can deregister it for non-admin pages:

Test afterwards. Some front-end features, like certain membership or chat plugins, may rely on Heartbeat.

Use a plugin if you prefer

Several performance plugins include Heartbeat controls, letting you choose intervals or disable it per location: dashboard, post editor and front end. They’re convenient for sites without a developer.

Step 3: Deal with heavy plugin AJAX

Heartbeat is only one source of admin-ajax load. Plugins often cause more:

  • Cart fragments in WooCommerce update the mini cart via AJAX on page loads. On sites where the mini cart doesn’t need constant updating, limiting cart fragments to shop pages reduces requests.
  • Live search plugins sending a request on every keystroke, without waiting for typing to pause.
  • Analytics or statistics plugins that record visits through AJAX on every page view.
  • Popup and notification plugins polling for updates.
  • Filters and infinite scroll making many requests per visitor.

For each, consider:

  • Is the feature necessary?
  • Can it be configured to make fewer requests?
  • Can it be replaced with a lighter alternative?
  • Can it run only on pages where it’s needed?

Step 4: Consider the REST API for custom work

If you build custom features, the REST API is often a better choice than admin-ajax.php:

  • REST endpoints are structured and easier to document and secure.
  • Responses for public data can be cached by CDNs or browsers.
  • You can design endpoints that load only what’s needed.

REST requests still load WordPress, so they’re not free, but they’re more flexible to optimise and cache.

Step 5: Protect the server

On servers you control:

  • Make sure PHP-FPM has enough workers to handle background requests alongside real visitors.
  • Use a persistent object cache, so AJAX requests run faster.
  • Rate limit admin-ajax.php for anonymous visitors if bots abuse it, while allowing legitimate use.
  • Monitor admin-ajax request volume as part of regular performance reviews.

Team habits

Simple habits help too:

  • Encourage staff to close admin tabs they’re not using.
  • Avoid leaving dashboards with live-updating widgets open all day unless needed.
  • Review plugins that add real-time features to the admin, and turn off those nobody uses.

A real example

On one WooCommerce site I worked on, the client complained that the server became sluggish every weekday afternoon. Traffic didn’t explain it. The access logs showed thousands of admin-ajax.php requests per hour during office hours. Five staff members each had several WooCommerce admin tabs open all day, and a reporting plugin attached a heavy database query to every Heartbeat request. Slowing Heartbeat to 60 seconds on admin pages, keeping it at its default in the editor, and replacing the reporting plugin’s live widget with a scheduled report cut admin-ajax traffic dramatically. The afternoon slowdowns disappeared.

Check after plugin changes

New plugins sometimes add their own Heartbeat or AJAX activity. After installing or updating plugins with live admin features, take a quick look at the network tab on an admin page to see whether background requests have increased. Catching a chatty plugin early is much easier than diagnosing a slow server months later.

Combine with monitoring

Add admin-ajax request counts to your regular server monitoring. A sudden jump after a plugin update or a new staff member’s workflow is easy to spot when you have a baseline to compare against.

Frequently asked questions

Should I disable the Heartbeat API completely?

Usually not. Disabling it in the post editor breaks autosave and post locking. Slowing it down in the admin and disabling it on the front end, where it’s rarely needed, is a safer approach.

Why is admin-ajax.php using so much CPU?

Each request loads WordPress and all plugins. Many open admin tabs, frequent Heartbeat intervals and plugins making repeated AJAX calls can add up to significant load.

Can admin-ajax requests be cached?

Generally not with page caching, because they’re dynamic and often personalised. Speed them up with an object cache and by reducing unnecessary requests.

Is the REST API faster than admin-ajax?

Not inherently, but REST endpoints can be designed to do less work and, for public data, can be cached. They’re generally better for new custom features.

Final thoughts

admin-ajax.php and the Heartbeat API are useful parts of WordPress that can quietly consume a lot of server resources. Measure how often they’re called, slow Heartbeat down in the admin, keep it in the editor, remove it from the front end where it isn’t needed, fix plugins that make excessive AJAX requests and prefer the REST API for new custom features. Your server will spend more of its time serving real visitors.