If your WordPress admin feels sluggish, your server load is mysteriously high, or your speed tests show slow backend responses, there is a good chance the culprit is a file you have never thought about: admin-ajax.php.
This unassuming file is WordPress’s AJAX endpoint: the doorway plugins use for background tasks like autosaving, checking for updates, and live notifications. The problem: every request to it loads the entire WordPress core, and some plugins hammer it constantly. This guide shows you how to find out if admin-ajax.php is your problem, identify the exact culprit, and fix it, without breaking anything.
Quick note on method: this is a diagnostic workflow, not a benchmark. Every site’s plugin mix is different, so the goal is to find your specific offender, not to quote universal numbers.
The Quick Verdict
Short on time? Here is the summary:
- admin-ajax.php itself is not the villain. It is a messenger. The real problem is almost always a plugin (or the Heartbeat API) calling it too often or doing too much work per call.
- Find the culprit with Query Monitor or your browser’s DevTools Network tab, filtered to admin-ajax.
- Fix it by taming the Heartbeat API, reconfiguring or replacing the offending plugin, and adding object caching so each call costs less.
- Never just block admin-ajax.php: carts, forms, and half the admin area depend on it.
What admin-ajax.php Actually Does
WordPress is built for page loads, but modern plugins need background communication: autosaving a draft, checking whether someone else is editing a post, polling for new notifications, validating a form field. admin-ajax.php is the standard endpoint for all of it.
Here is the catch: unlike a cached page (which can skip PHP entirely), every admin-ajax.php request boots the full WordPress stack: core, theme, all active plugins, and the database connection. One request is cheap. But when a plugin fires one every 15 seconds for every logged-in user and every visitor, the cost multiplies fast:
- 10 logged-in users × a heartbeat every 15 seconds = 40 full WordPress boots per minute, doing nothing useful most of the time
- A badly coded plugin polling on the frontend adds the same load from visitors, who cannot even benefit from it
That is why admin-ajax.php shows up in server resource graphs and “time to first byte” complaints far more than its humble name suggests.
Step 1: Confirm admin-ajax.php Is the Problem
Method A: Browser DevTools (2 minutes, no plugin needed)
- Open your site (or wp-admin) in Chrome/Firefox.
- Open DevTools (F12) → Network tab.
- In the filter box, type
admin-ajax. - Watch for 30–60 seconds. Each row is one request — note the Time column and how often new rows appear.
- Click any row → Payload tab → look for the
actionparameter. That action name usually reveals the plugin (e.g.,heartbeat, or a plugin-specific prefix).
If you see requests every few seconds with meaningful response times, you have found a live problem. If the Network tab is quiet, your issue lies elsewhere.
Method B: Query Monitor (more detail)
Install the free Query Monitor plugin, then load the affected pages. Its overview shows slow database queries and HTTP API calls, and the request timing helps you see whether AJAX handling is where time goes. It is the fastest way to connect “slow” to a specific component.
Method C: Server access logs
If you have log access, count admin-ajax.php hits over an hour. A healthy site shows modest numbers; a sick one shows thousands. This is the most honest measurement because it includes all visitors, not just your test browser.
Step 2: Identify the Culprit
Match the action parameter from DevTools to these usual suspects:
| Symptom | Likely culprit | What to check |
|---|---|---|
| Requests every 15–60s in wp-admin | Heartbeat API | Post editor, dashboard widgets |
| Constant frontend polling | Live chat, notification, or “recent activity” plugin | Plugin settings for refresh intervals |
| Slow single calls (seconds each) | Plugin doing heavy work per request (stats, related posts, security scans) | Query Monitor’s slow-query list |
| Spikes on specific pages | Page builder or form plugin with autosave/preview polling | Editor/preview settings |
| High admin-ajax in access logs, low in your browser | Affects logged-in users or specific roles broadly | Any plugin with per-user polling |
The Heartbeat API deserves special attention: it is WordPress core (not a plugin), it runs in the post editor and dashboard by default, and on sites with many editors it is often the single biggest admin-ajax consumer.
Step 3: Fix It (In Order of Impact)
1. Tame the Heartbeat API
You do not need to nuke it. The editor genuinely uses it for autosave and post locking. Instead, control where and how often it runs:
- Install Heartbeat Control (free) or use the heartbeat settings in WP Rocket / Perfmatters if you already run one.
- Sensible starting point: disable heartbeat on the frontend entirely (visitors never need it), slow it in the admin dashboard (e.g., 60 seconds), and leave it normal in the post editor where autosave matters.
- Verify: watch DevTools again — frontend admin-ajax traffic should drop to near zero.
2. Reconfigure the offending plugin
For plugin-driven polling, open that plugin’s settings and look for anything like “refresh interval,” “live updates,” “check every X seconds,” or “real-time.” Options, in order of preference:
- Increase the interval (every 5 minutes instead of every 15 seconds).
- Disable the polling feature if you do not use it (do you really need live dashboard notifications?).
- Replace the plugin with one that uses a more efficient mechanism — or with no plugin at all, if the feature was marginal.
3. Make each call cheaper with object caching
You cannot always stop the calls, but you can make them cost less. An object cache (Redis or Memcached) means repeated database queries inside those AJAX handlers get served from memory instead of MySQL. It does not fix a chatty plugin, but it can cut the per-request cost dramatically, especially under many simultaneous users. Our Redis setup guide covers this.
4. Fix it properly: move work out of the request
For developers: the durable fix for a heavy custom AJAX handler is to not do the heavy work inside the request at all. Schedule it via WP-Cron, cache the result in a transient, and have the AJAX call read the cached result. If a plugin you rely on is the offender and the author will not fix it, that is a strong signal to switch plugins.
What NOT to Do
- Do not block admin-ajax.php in .htaccess, Cloudflare, or a security plugin. WooCommerce carts, contact forms, the block editor, and countless plugin features break instantly. And the breakage is confusing to diagnose.
- Do not disable the Heartbeat API entirely unless you understand the tradeoff: you lose editor autosave and post-lock warnings. Tame it per-location instead.
- Do not install five “disable heartbeat” plugins at once. One control point is enough; overlapping plugins create the same class of conflict as overlapping cache plugins.
Who This Matters Most For
- Membership/community sites: many logged-in users = many heartbeat and polling requests. Taming heartbeat is often the single biggest admin-side win.
- WooCommerce stores: cart fragments use admin-ajax on every page load for logged-in users — make sure fragment caching and object caching are in place, and do not let a chatty plugin add to it.
- Multi-author blogs: the post editor is heartbeat central. Per-location heartbeat control pays off immediately.
- Everyone: frontend polling from a plugin you barely use is pure waste. Audit with DevTools once a quarter.
Frequently Asked Questions
Is admin-ajax.php a security risk?
It is a common target for brute-force probing because it is always present, but the file itself is not a vulnerability — the risk is poorly-coded plugin actions that fail to check permissions. Keep plugins updated, and the performance fixes in this guide do not change your security posture either way.
Why is admin-ajax.php slow even with no visitors?
Because most of its traffic comes from logged-in users and the admin area, not visitors. Heartbeat in the editor, dashboard widgets polling, and admin-side plugin features all fire with zero frontend traffic. Check DevTools while sitting in wp-admin doing nothing — that is the honest test.
Can caching fix slow admin-ajax.php?
Page caching does not apply — AJAX responses are dynamic and uncacheable by nature. Object caching (Redis/Memcached) helps by making each call’s database work cheaper. The real fix is reducing call frequency and per-call work, as described above.
What is a normal admin-ajax.php request rate?
There is no universal number, but as a rule of thumb: on the frontend for logged-out visitors it should be near zero; in the post editor, heartbeat every 15–60 seconds is normal; constant sub-15-second polling from any single source is worth investigating.
I disabled a plugin and admin-ajax.php is still busy — now what?
Clear your browser cache and check in an incognito window (a cached page can keep calling a removed plugin’s endpoint until refreshed). Then re-run the DevTools filter and read the action parameters fresh — there may be more than one culprit, which is common.
The Bottom Line
admin-ajax.php is a symptom, not the disease. Spend 10 minutes with DevTools filtered to admin-ajax, read the action parameters, and you will almost always find one plugin, or the Heartbeat API, doing the damage. Tame the heartbeat per location, calm down or replace the chatty plugin, add object caching so remaining calls cost less, and never “fix” it by blocking the file. Your server (and your editors) will thank you.

