Opens in a new tab
  1. Home
  2. Guides
  3. System
System guide

The WordPress Heartbeat API, explained

Learn how the WordPress Heartbeat API communicates with the server, powers post locking and autosaves, affects admin load and can be tuned safely.

  • Updated September 3, 2026
  • 22 min read
  • WordPress guide

The WordPress Heartbeat API is a built-in polling system that allows the browser and the WordPress server to exchange data periodically while a page remains open.

It is responsible for some of the near-real-time behavior users experience inside WordPress, especially in the administration area.

Heartbeat can participate in features such as:

  • post locking;
  • autosaves;
  • editing-session checks;
  • nonce refreshes;
  • session-related updates;
  • plugin-defined background communication.

Because Heartbeat generates recurring requests, it is also frequently blamed for high admin-ajax.php traffic and WordPress backend load.

That criticism is sometimes justified, but the usual advice to simply disable Heartbeat can be dangerously simplistic.

The correct question is not:

Can I turn Heartbeat off?

It is:

What depends on Heartbeat on this site, how often is it running, and can its workload be reduced without damaging important functionality?

This guide explains how the WordPress Heartbeat API works, how browser polling reaches the server, which Core features depend on it, how developers can use it, why it can create server load and what happens when you slow it down or disable it.

What is the WordPress Heartbeat API?

The WordPress Heartbeat API is a server polling API built into WordPress.

The official WordPress Heartbeat API documentation describes it as a mechanism for providing near-real-time updates between the browser and server.

Unlike a persistent WebSocket connection, Heartbeat works by periodically sending HTTP requests.

A simplified cycle looks like this:

WordPress page opens
↓
Heartbeat JavaScript starts
↓
timer reaches next tick
↓
browser gathers Heartbeat data
↓
AJAX request is sent to WordPress
↓
server processes Heartbeat data
↓
server returns JSON response
↓
browser processes response
↓
next Heartbeat cycle begins

The connection is therefore not permanently open.

The browser repeatedly checks in with WordPress.

Heartbeat was introduced in WordPress 3.6

The main Heartbeat infrastructure was introduced in WordPress 3.6.

Since then, Core and plugins have used it as a general communication channel for periodic browser-to-server updates.

Heartbeat is not limited to the post editor

The post editor is where Heartbeat is most visible because important editorial features use it.

However, the API itself is more general.

Heartbeat can operate in:

  • WordPress administration screens;
  • the post editor;
  • frontend contexts when explicitly used;
  • logged-in contexts;
  • certain logged-out implementations.

How the WordPress Heartbeat cycle works

Heartbeat coordinates JavaScript events in the browser with AJAX processing on the WordPress server.

The official API documentation describes three basic stages:

  • adding data before the request is sent;
  • processing that data on the server;
  • handling the returned response in JavaScript.

The browser creates a Heartbeat tick

When Heartbeat is running, its JavaScript periodically initiates what WordPress calls a tick.

The browser can collect information that Core or plugins want to send to the server.

Developers can hook into the client-side:

heartbeat-send

event to add custom data.

A simple example is:

jQuery( document ).on( 'heartbeat-send', function( event, data ) {
    data.my_plugin_status = 'check';
} );

The next Heartbeat request can then carry that information to WordPress.

The server receives the request

For authenticated users, WordPress processes the request through the wp_ajax_heartbeat() function.

That function:

  • checks for the Heartbeat nonce;
  • determines the current screen ID;
  • retrieves data sent by the browser;
  • passes the data through Heartbeat filters;
  • adds response information;
  • returns JSON to the browser.

The browser processes the response

Once WordPress responds, JavaScript fires the:

heartbeat-tick

event.

Core or plugin JavaScript can then inspect the returned data and update the interface.

This gives developers a recurring communication cycle without building a completely separate polling system.

Heartbeat uses admin-ajax.php

One reason site owners notice Heartbeat is that requests commonly appear as traffic to:

wp-admin/admin-ajax.php

WordPress AJAX requests use this endpoint for many different actions, and Heartbeat is one of them.

Seeing repeated requests to admin-ajax.php therefore does not automatically mean Heartbeat is responsible.

You need to inspect the AJAX action.

The Heartbeat AJAX action

Heartbeat requests use the action associated with the Heartbeat handler.

Browser developer tools commonly make it possible to inspect the request payload and identify:

action=heartbeat

This is useful when diagnosing recurring backend traffic.

admin-ajax.php is only the transport

It is important not to confuse:

admin-ajax.php
=
problem

with reality.

admin-ajax.php is simply the WordPress AJAX endpoint.

The actual cost depends on what the specific action does.

A Heartbeat request that performs almost no custom work can be inexpensive.

A plugin can also hook into every Heartbeat request and perform expensive database queries or remote API calls.

The URL alone tells you very little about the cost.

How often does WordPress Heartbeat run?

The official WordPress documentation describes Heartbeat polling intervals generally ranging from approximately:

15 to 120 seconds

The exact behavior depends on context and configuration.

Heartbeat does not necessarily use the same interval everywhere.

The interval is configurable

WordPress provides the:

heartbeat_settings

filter.

The official heartbeat_settings documentation allows developers to modify Heartbeat settings, including the interval.

For example:

add_filter( 'heartbeat_settings', function( $settings ) {
    $settings['interval'] = 60;
    return $settings;
} );

This example requests a 60-second interval.

The polling interval affects request volume

Consider one open WordPress admin session.

A simplified comparison is:

15-second interval
→ approximately 4 requests per minute

30-second interval
→ approximately 2 requests per minute

60-second interval
→ approximately 1 request per minute

120-second interval
→ approximately 1 request every 2 minutes

Now multiply that across:

  • multiple administrators;
  • multiple open tabs;
  • several editors;
  • plugins adding work to each request.

The difference can become meaningful on busy sites.

What data does Heartbeat send?

Heartbeat is not limited to one fixed payload.

Core and plugins can add data to the request.

The browser sends a collection of values, while WordPress can return another collection in the JSON response.

The screen ID is part of the request context

The authenticated Heartbeat handler receives a:

screen_id

value.

This lets WordPress and plugins know which administration context triggered the Heartbeat request.

That matters because a plugin may need Heartbeat processing on one screen but not another.

Plugins can add custom data

A plugin can add information through the JavaScript heartbeat-send event.

On the PHP side, it can receive that information through:

heartbeat_received

and return additional response data.

The official heartbeat_received hook receives:

  • the current response array;
  • the data received from the browser;
  • the current screen ID.

Servers can also add data without receiving custom data

WordPress also exposes:

heartbeat_send

which filters the response being sent back to the browser.

This allows server-side code to add information to Heartbeat responses even when that data was not directly requested by a custom field in the incoming payload.

The heartbeat_tick action runs on the server

WordPress additionally fires:

heartbeat_tick

during authenticated Heartbeat processing.

This provides another extension point for developers.

Heartbeat and post locking

One of the most important WordPress Core features associated with Heartbeat is post locking.

Post locking helps prevent two users from unknowingly editing the same piece of content at the same time.

For example:

Editor A opens Post 123
↓
WordPress establishes editing state
↓
Heartbeat keeps the session current
↓
Editor B opens Post 123
↓
WordPress detects Editor A's active lock
↓
Editor B sees a warning or takeover workflow

For the complete mechanism, see WordPress post locking, explained.

Heartbeat refreshes editing locks

WordPress Core includes:

wp_refresh_post_lock()

The function checks the lock status on the post editing screen and refreshes the lock when appropriate.

This matters because a post lock cannot simply be created once and remain permanent.

WordPress needs to distinguish:

user is still editing

from:

user closed the browser 20 minutes ago

Heartbeat provides the recurring communication needed to keep that state current.

Disabling Heartbeat can affect lock freshness

If Heartbeat no longer runs in the editor, WordPress loses the normal recurring channel used to refresh the editing lock.

The result can be unreliable collaborative behavior.

That is why globally disabling Heartbeat should never be presented as a harmless performance toggle on a multi-author site.

Heartbeat and WordPress autosave

Heartbeat also participates in WordPress autosave behavior.

Core includes the heartbeat_autosave() function, which performs autosave work through Heartbeat.

Autosave protects in-progress content

While users edit content, WordPress can periodically preserve their work.

This reduces the damage caused by:

  • browser crashes;
  • internet interruptions;
  • accidental navigation;
  • session problems;
  • other editing failures.

Autosave is not the same thing as Heartbeat

These concepts are closely related but distinct.

Heartbeat is the communication mechanism.

Autosave is a content-preservation feature that can use that mechanism.

Think of it as:

Heartbeat
→ transport / recurring communication

Autosave
→ one feature using that communication

Autosave is also not the same as revisions

WordPress revisions preserve historical content states.

Autosaves protect current work.

Revision retention is therefore a separate consideration.

See How WordPress post revisions work for the broader revision system.

Heartbeat and WordPress nonces

Heartbeat also participates in keeping certain WordPress security tokens current during long administration sessions.

Authenticated Heartbeat requests themselves use a nonce.

The wp_ajax_heartbeat() implementation verifies the Heartbeat nonce before processing the request.

WordPress can refresh expiring nonces

Long editing sessions create a practical problem.

A user can keep an administration screen open for a long time while nonce-based actions eventually approach expiration.

WordPress uses Heartbeat-related refresh mechanisms to update relevant nonces.

Core includes functions such as:

wp_refresh_post_nonces()

wp_refresh_heartbeat_nonces()

to support these workflows.

Nonces are not authorization

A nonce should not be confused with a user capability check.

The official WordPress nonce documentation explicitly warns that nonces should not be used as authentication, authorization or access control.

Plugins still need appropriate capability checks for privileged operations.

Heartbeat can also work for logged-out users

Heartbeat is often described exclusively as a logged-in WordPress admin feature.

That is incomplete.

WordPress Core also includes:

wp_ajax_nopriv_heartbeat()

The official wp_ajax_nopriv_heartbeat() documentation describes the handler used when the current visitor is not logged in.

Separate no-privilege hooks exist

Logged-out Heartbeat processing has its own extension points:

  • heartbeat_nopriv_received;
  • heartbeat_nopriv_send;
  • heartbeat_nopriv_tick.

This means developers can build frontend polling behavior on top of Heartbeat without requiring an authenticated WordPress session.

Frontend Heartbeat should still be justified

Just because Heartbeat can run on the frontend does not mean every plugin should enable continuous polling for anonymous visitors.

On a high-traffic public website, recurring AJAX requests from large numbers of visitors can create substantially more load than a small editorial team inside wp-admin.

Frontend use should therefore be deliberate.

Why WordPress Heartbeat can create server load

A Heartbeat request still executes WordPress.

It is not a free browser-side timer.

The server must process an AJAX request and run any relevant callbacks.

The impact depends on:

  • number of active sessions;
  • number of open tabs;
  • polling interval;
  • server resources;
  • database queries executed;
  • plugin callbacks attached to Heartbeat;
  • remote requests triggered by plugins;
  • response size.

One user can generate Heartbeat from multiple tabs

Suppose one editor has:

  • the Dashboard open;
  • the Posts screen open;
  • two post editors open;
  • a plugin settings page open.

The site’s workload should not be thought of only as:

1 logged-in user

because several active browser contexts may be generating background activity.

Concurrency is more important than one request

A single Heartbeat request may be inexpensive.

But:

50 editors
×
several open tabs
×
frequent polling

can create a meaningful stream of PHP requests.

For a broader backend-performance strategy, read Reducing WordPress admin server load.

Plugins can make each tick more expensive

Heartbeat becomes much more problematic when plugins attach costly operations to every cycle.

Examples include:

  • multiple database queries;
  • large metadata scans;
  • external API calls;
  • large JSON payloads;
  • repeated calculations that should be cached.

If Heartbeat traffic is expensive, inspect what is attached to Heartbeat before assuming the API itself is the entire problem.

How to measure WordPress Heartbeat activity

Before changing Heartbeat configuration, measure what the site is actually doing.

Use the browser Network panel

Open your browser developer tools while using WordPress.

Filter requests for:

admin-ajax.php

and inspect recurring requests.

For Heartbeat, look for:

action=heartbeat

Record:

  • request frequency;
  • request duration;
  • response size;
  • HTTP errors;
  • whether timing changes between screens.

Compare different admin contexts

Test:

  • Dashboard;
  • Posts;
  • post editor;
  • plugin settings screens;
  • frontend while logged in.

Heartbeat may behave differently depending on the context.

Profile the server-side request

If an individual Heartbeat request is slow, profile it like any other WordPress request.

Inspect:

  • database queries;
  • PHP callbacks;
  • plugin hooks;
  • remote HTTP requests;
  • object-cache activity;
  • memory usage.

Tools such as Query Monitor, application performance monitoring and server profiling can help identify the real cost.

Should you disable the WordPress Heartbeat API?

Sometimes reducing or disabling Heartbeat in a specific context can be reasonable.

Globally disabling it without understanding dependencies is much harder to justify.

When restriction may make sense

Potential candidates include contexts where:

  • Heartbeat provides no useful functionality;
  • recurring polling creates measurable server load;
  • the site has very limited server resources;
  • another architecture replaces the required functionality;
  • a specific frontend integration does not need continuous polling.

When disabling it can be risky

Be especially cautious when the site has:

  • multiple editors;
  • long post-editing sessions;
  • collaborative editorial workflows;
  • plugins that explicitly depend on Heartbeat;
  • custom frontend Heartbeat behavior.

The post editor is generally the context where blindly disabling Heartbeat creates the greatest risk.

Reducing Heartbeat frequency versus disabling it

There is an important middle ground between:

leave everything at default

and:

disable Heartbeat completely

You can reduce polling frequency.

A longer interval reduces request volume

For example, changing an effective polling interval from:

15 seconds
to
60 seconds

can reduce the theoretical request rate for that active context by roughly 75%.

This does not mean every site should use 60 seconds.

It demonstrates why frequency is a useful tuning control.

A longer interval also delays updates

The tradeoff is that Heartbeat-dependent information is refreshed less frequently.

This can make:

  • post-lock changes slower to appear;
  • session-related updates less responsive;
  • plugin-driven real-time interfaces feel delayed.

An interval can therefore become so long that functionality technically works but feels broken to users.

Heartbeat and autosave frequency should be tuned separately

One recurring mistake is treating:

  • Heartbeat frequency;
  • autosave frequency;
  • revision retention;

as though they were one WordPress setting.

They are not.

A useful model is:

Heartbeat frequency
→ communication frequency

Autosave interval
→ content preservation frequency

Revision retention
→ historical version retention

Each should be evaluated according to its own purpose.

How developers can use the Heartbeat API

Heartbeat is not merely a Core implementation detail.

WordPress exposes it as an API for plugins.

Send custom data from JavaScript

Developers can add information to the outgoing payload:

jQuery( document ).on( 'heartbeat-send', function( event, data ) {
    data.my_plugin = {
        check_status: true
    };
} );

Process the data in PHP

A plugin can then use:

heartbeat_received

to process the request.

For example:

add_filter(
    'heartbeat_received',
    function( $response, $data, $screen_id ) {

        if ( empty( $data['my_plugin']['check_status'] ) ) {
            return $response;
        }

        if ( ! current_user_can( 'edit_posts' ) ) {
            return $response;
        }

        $response['my_plugin'] = array(
            'status' => 'ready',
        );

        return $response;
    },
    10,
    3
);

Handle the returned data in JavaScript

The browser can listen for:

heartbeat-tick

and update the interface:

jQuery( document ).on( 'heartbeat-tick', function( event, data ) {

    if ( ! data.my_plugin ) {
        return;
    }

    console.log( data.my_plugin.status );
} );

Keep Heartbeat callbacks lightweight

A Heartbeat callback can execute repeatedly for every active session.

That makes inefficient code especially dangerous.

Avoid performing unnecessary:

  • large queries;
  • full table scans;
  • remote API calls;
  • large object serialization;
  • work unrelated to the current screen.

Best practices for plugin developers

Heartbeat should be treated as recurring infrastructure rather than a convenient place to run arbitrary background work.

Check whether the current screen needs your callback

The Heartbeat request provides a screen ID.

Use it when functionality is screen-specific.

Do not perform expensive editor-related work on unrelated admin pages.

Send only the data you need

Heartbeat is not designed to transport giant application payloads every few seconds.

Keep request and response data compact.

Cache reusable server-side results

If the same expensive result will be returned across multiple Heartbeat cycles, consider appropriate caching instead of recalculating it every time.

Use capabilities for privileged operations

Do not assume that because a request came through authenticated Heartbeat, the user is authorized to perform every possible action.

Use capability checks such as:

current_user_can()

for protected operations.

Do not turn Heartbeat into a job queue

Heartbeat can trigger lightweight recurring updates.

Large imports, exports, image processing jobs or expensive AI generation should generally use architecture designed for long-running work rather than tying execution to a user’s open browser tab.

Common Heartbeat misconceptions

“Heartbeat is a WebSocket connection”

Incorrect.

Heartbeat is a polling API based on recurring requests.

“Heartbeat always runs every 15 seconds”

Incorrect.

WordPress Heartbeat timing varies by context and configuration, with the documented polling range generally spanning approximately 15 to 120 seconds.

“Every admin-ajax.php request is Heartbeat”

Incorrect.

WordPress and plugins use admin-ajax.php for many AJAX actions.

“Heartbeat only works inside wp-admin”

Incorrect.

WordPress supports frontend and no-privilege Heartbeat implementations.

“Heartbeat is only used for autosave”

Incorrect.

Autosave is one feature associated with Heartbeat, but Core also uses the mechanism for editing locks, nonce refreshes and other state updates.

“Disabling Heartbeat has no functional consequences”

Incorrect.

Features and plugins can depend on it.

“More Heartbeat requests automatically mean a site is badly optimized”

Incorrect.

Request frequency, request cost, concurrent users and server capacity all matter.

“Setting the longest interval is always best for performance”

Incorrect.

A longer interval reduces request frequency but can degrade the responsiveness of features that rely on Heartbeat.

How TheOneWP can control WordPress Heartbeat

TheOneWP includes separate controls for Heartbeat behavior and related editing-performance settings.

Heartbeat

Heartbeat lets administrators control where the WordPress Heartbeat mechanism remains enabled.

This is useful when the post editor still needs Heartbeat-dependent functionality but other contexts do not require the same recurring polling.

Heartbeat Frequency

Heartbeat Frequency controls how frequently Heartbeat polls the server.

Instead of choosing only between default behavior and complete removal, administrators can reduce request frequency while preserving the API.

Autosave Interval

Autosave Interval controls how frequently WordPress automatically preserves editing work.

This should be configured separately from Heartbeat polling.

Post Revisions

Post Revisions controls revision retention.

This addresses long-term content-history growth rather than Heartbeat request frequency.

A practical Heartbeat optimization workflow

  1. Open browser developer tools.
  2. Identify Heartbeat requests through action=heartbeat.
  3. Measure request frequency.
  4. Measure request duration.
  5. Compare Dashboard, editor and other admin screens.
  6. Profile slow Heartbeat requests server-side.
  7. Identify plugins attached to Heartbeat hooks.
  8. Check whether expensive callbacks are screen-specific.
  9. Test a longer polling interval if request volume is genuinely significant.
  10. Keep Heartbeat active in the editor when post locking and collaboration matter.
  11. Test autosave behavior.
  12. Test post locking with two separate users.
  13. Test long editing sessions for nonce/session problems.
  14. Compare server load before and after the change.

WordPress Heartbeat API checklist

  • Understand that Heartbeat is polling, not WebSockets.
  • Expect recurring AJAX requests while Heartbeat is active.
  • Identify Heartbeat using the AJAX action rather than the URL alone.
  • Remember that documented intervals generally range from 15 to 120 seconds.
  • Do not assume every screen uses the same effective interval.
  • Do not disable Heartbeat globally without checking dependencies.
  • Test post locking after changing Heartbeat behavior.
  • Test autosave after changing Heartbeat behavior.
  • Keep Heartbeat callbacks lightweight.
  • Use the screen ID to avoid unnecessary processing.
  • Keep custom request and response payloads small.
  • Cache repeated expensive results where appropriate.
  • Use capabilities for protected operations.
  • Do not use Heartbeat as a replacement for a proper background-job architecture.
  • Measure concurrent activity, not only one isolated request.
  • Consider multiple browser tabs when estimating load.
  • Profile plugins that attach work to every Heartbeat tick.
  • Change polling frequency only after establishing a baseline.
  • Separate Heartbeat frequency from autosave timing and revision retention.

Related guides

Final thoughts

The WordPress Heartbeat API is a small piece of infrastructure with a surprisingly large role in the WordPress editing experience.

Its basic job is simple:

browser waits
↓
Heartbeat tick occurs
↓
data is sent to WordPress
↓
server processes it
↓
JSON response returns
↓
browser reacts
↓
cycle repeats

But that recurring communication supports important functionality.

Post locks need current editing state.

Autosaves need a mechanism for preserving work.

Long administration sessions can benefit from refreshed nonces and session information.

Plugins can also use the API for their own near-real-time updates.

This is why disabling Heartbeat purely because admin-ajax.php appears repeatedly in a network log is not a good optimization strategy.

At the same time, Heartbeat should not be exempt from performance scrutiny.

A large number of concurrent sessions, aggressive polling intervals or expensive plugin callbacks can turn a lightweight recurring request into meaningful server load.

The best approach is therefore measured rather than absolute.

Determine where Heartbeat runs, how frequently it runs and what each request actually does.

Keep it where WordPress collaboration and editing features depend on it.

Reduce unnecessary polling where measurement shows a real benefit.

And when plugins extend Heartbeat, make every recurring callback as small, targeted and cache-friendly as possible.

That preserves the functionality Heartbeat was built to provide without making the server perform more work than the site genuinely needs.

Simplify your WordPress stack

A modular WordPress toolkit. 104 focused tools.

Ultimately, you can build cleaner workflows, maintain fewer plugins and enable only the features each website actually needs.