Why WordPress admin-ajax.php Is Slow (and How to Find and Fix the Real Cause)

You open the WordPress dashboard, and it loads, but something drags. In the browser’s Network panel, a request to admin-ajax.php hangs around for several seconds. The filename tells you nothing, so you’re left wondering which plugin or feature is behind it.

You don’t have to guess. Many WordPress features send requests through admin-ajax.php, so the filename alone can’t point to the cause.

The request itself holds the clue, and This guide shows you how to read that clue, trace it to the plugin or task behind it, and figure out where to look first.

If the lag affects more than one request or screen, start with the broader checks for a slow WordPress admin.

TL;DR: Find the action name in the slow request, read the response, trace that action to the code that handles it, and test every change on staging. Heartbeat is the most common culprit, but turning it off breaks autosave, so slow it down instead.For public-page caching and frontend optimization, Airlift can help; slow AJAX handlers still need targeted fixes.

What admin-ajax.php does

Every request to admin-ajax.php includes an action value. WordPress uses that value to pick the handler, the function that does the actual work. Core, themes, and plugins all share this one entry point.

Think of it as one front door leading to many offices. The door isn’t the reason the building is slow; the office receiving the most visitors is.

Frontend WordPress page with the logged-in Query Monitor toolbar submenu expanded

How to find the slow request

Open your browser’s developer tools, select the Network tab, reload the screen where you see the lag, and filter for admin-ajax.php. Sort by duration and open the slowest request.

Note four things: the action value, the request method, the status code, and the response body. The initiator column also shows which script sent the request.

📝 Note: Check whether the request repeats. A request that fires every few seconds can add up to more work over an hour than one long request that fires once. If your host also reports high CPU usage in WordPress, compare the spike with the timing of those requests.

What the response tells you

The response body often explains more than the duration does.

  • A response of 0 means no handler matched the action. WordPress’s older Codex documentation describes this behavior. Check for a deactivated plugin or a typo in the action name.
  • A long wait with a normal response points to heavy work inside the handler, such as large database queries or a call to an outside service.
  • A 5xx status or a timeout points to a server or code limit. The server’s error log will name the actual problem.

📝 Note: A request can return HTTP 200 and still contain an error message, so always read the body.

How to trace the action to its code

WordPress registers handlers with two hooks:

  • wp_ajax_{action} runs for logged-in users.
  • wp_ajax_nopriv_{action} runs for logged-out visitors.

If your action is my_report_fetch, search your plugins and theme for wp_ajax_my_report_fetch. The file that registers it is where your investigation continues.

Heartbeat Control frontend settings with Modify Heartbeat and frequency controls

If nothing matches, the action may have come from a plugin you’ve removed or from a page builder script. The initiator column usually reveals which one. If the initiator points to an old script from a removed plugin, clear the relevant cache and reload before tracing the request again.

Heartbeat: the usual suspect

Heartbeat is a built-in feature that sends regular requests to admin-ajax.php while someone works in the admin. It powers autosave, post locking, and login checks, which is why it’s useful and why it often gets blamed.

The default interval varies by WordPress version and setup, so check the heartbeat.js on your own install rather than trusting a number from a blog post.

WordPress post editor with Query Monitor open while Heartbeat requests run

In our test, we seeded a draft and watched the editor sit idle for 20 seconds. The browser sent three Heartbeat POST requests, and each returned HTTP 200 with a post lock refresh and an authentication check. An idle tab can keep the server busy like that. We ran this once on a single site, so treat it as an illustration rather than a benchmark.

Slow it down, don’t switch it off

Disabling Heartbeat breaks autosave and post locking, as Delicious Brains notes, and that can mean lost drafts and two editors overwriting each other. Adjust the interval instead with the heartbeat_settings filter:

add_filter( 'heartbeat_settings', function( $settings ) {
    $settings['interval'] = 60;
    return $settings;
});
Heartbeat Control settings showing separate Dashboard, Frontend, and Post editor controls

Confirm the change in the Network panel. If your new interval doesn’t take effect, a plugin or the core code may be overriding it.

Heartbeat Control dashboard settings with Modify Heartbeat and frequency controls

📝 Note: Heartbeat requests are POST requests, and Delicious Brains notes they bypass page caching. A cache rule won’t reduce them, so adjust the interval or the screens where Heartbeat runs.

Use Query Monitor to see who’s doing the work

Query Monitor is a free debugging plugin that shows what happens during a request. On staging, it can reveal which plugin, theme, or function runs each database query.

WordPress dashboard with the Query Monitor diagnostic submenu expanded
  • The queries panel, filtered by component or calling function, shows which plugin runs the most queries.
  • Slow query notifications flag queries that take longer than they should.
  • AJAX headers carry PHP errors and memory details for jQuery AJAX responses. They don’t list every query, so use the queries panel for detail.

By default, only administrators see its output. Install it on staging and keep it off a live site.

📝 Note: Query Monitor tells you where the work happens. You still need to change the code or the setting.

Three shortcuts that backfire

  • Don’t disable admin-ajax.php. Core, themes, and plugins depend on it, so breakage often shows up somewhere you won’t connect to the change.
  • Don’t add a blanket cache rule. Heartbeat bypasses caching, and a cached admin response can show one user’s data to someone else. If you’ve already changed cache rules, check for WordPress caching issues affecting dynamic or personalized responses.
  • Don’t move a slow query to a new endpoint and call it fixed. The expensive work moves with it.

You can still enable caching in WordPress for public pages, but keep admin and personalized AJAX responses out of shared page cache. That improves public-page delivery without fixing the slow handler itself. A WordPress caching plugin can help speed up public pages, but it won’t fix an expensive AJAX handler or reduce Heartbeat’s request frequency.

Should you move the action to REST?

Maybe, but don’t expect a speed boost. The REST API suits functionality you own and gives you clean permission checks. If the handler runs an expensive query, a REST route runs the same query. Treat any migration as a project with its own testing.

FAQs

What exactly is admin-ajax.php, and why does it matter?

admin-ajax.php is the single doorway WordPress uses to handle AJAX requests, and the action value in each request decides which handler does the work. Core, themes, and plugins all send requests through it, so one filename can cover many unrelated jobs. That’s why the filename alone never tells you what’s wrong.

Why is admin-ajax.php slow on my site?

A slow request usually means one action is either running too often, doing heavy database work, or waiting on an outside service. The request itself is rarely the culprit, so you need to find which action is slow before you change anything.

How do I find the plugin responsible?

Read the action value in the slow request, search your plugins and theme for the matching wp_ajax_ hook, and confirm the work on staging with Query Monitor. The hook tells you where the handler is registered, and Query Monitor shows which plugin or theme runs the queries during that request.

Does Heartbeat slow WordPress down?

Yes, it can, especially when several editor tabs are open at once. Measure the Heartbeat requests first, then adjust the interval rather than disabling the feature, because disabling it breaks autosave and post locking.

Should I disable admin-ajax.php?

No, because too many parts of WordPress depend on it. Blocking or disabling it tends to break features in places you won’t connect to the change, so target the specific action instead.

Conclusion

A slow admin-ajax.php request is a clue, not a diagnosis. Find the action, read the response, trace the handler, and test before you change anything. Often the answer is Heartbeat, and the better fix is a longer interval rather than a feature that’s switched off.

Your editors keep their autosave, and you know exactly which action was making the noise.

Written by

Akshat Choudhary

Akshat Choudhary is the founder and CEO of BlogVault, MalCare, and WP Remote. He builds and writes about WordPress products, security, site management, and performance, helping teams keep websites fast, resilient, and easier to operate.

Reading is the slow way to a fast site.

Airlift works out what each page needs and applies it. Free to try on your own site.