Slow WordPress admin: how to find the cause and fix it
The dashboard is never served from a page cache, so every screen waits on PHP and the database. Time one slow screen, read it in Query Monitor, then check outside requests, database queries, the object cache, PHP, Heartbeat, WP-Cron and the host, in that order.
- By
- WP Ministry
- Published
In short
- Time the slow screen in your browser's network panel first. The figure for the screen itself is the server's work. What comes after it is the browser's.
- Query Monitor shows, for the screen you are on, how long the database queries and the requests to other servers took, and which plugin made them.
- A plugin that calls another server on every screen is the first thing to rule out.
- Site Health reports oversized autoloaded options, a missing object cache, an old PHP version and an opcode cache that is off.
- Slow the Heartbeat. Do not switch it off, because post locks and the logged-out warning depend on it.
- Change one thing at a time, on a staging copy, and time the same screen again after each change.
A slow WordPress dashboard is almost always slow on the server. Visitors can be handed a saved copy of a page from a page cache. The dashboard never is: WordPress sends every dashboard screen with headers that forbid caching, so each one is built from scratch by PHP and the database. The cause is whatever makes that build slow: a plugin calling another server, heavy database queries, no object cache, an old or badly set up PHP, or a hosting plan at its limits.
So a fast home page says nothing about the dashboard. Visitors see the copy and you see the build, which how to reduce server response time covers from the visitor's side. Time one slow screen before you change anything: the figure tells you which cause to check.
Measure before you change anything
Step 1: Time one slow screen in the browser
Open the slow screen. Open your browser's developer tools (in Chrome, Control+Shift+J, or Command+Option+J on a Mac), select the Network panel and reload. The top row is the screen itself, with a name such as
edit.phporplugins.php. Its Time column is the total from the start of the request to the last byte of the answer.Step 2: Decide which side is slow
If that one row accounts for most of the delay, the server is slow and the rest of this page applies. Its Timing tab splits the total into "Waiting (TTFB)" and "Content Download". On a normal connection, count both as the server's time, because PHP can start sending a page while it is still building the rest. If the row finishes quickly and the screen takes seconds more to become usable, the time is going to scripts in your browser, which happens most in the block editor.
Step 3: Compare screens, and the front of the site
Time the Dashboard, the Posts list, the Plugins screen and the editor, and write the figures down. One slow screen points to something that screen does. Every screen slow by about the same amount points to something loaded on all of them, or to the server. Then time a page on the front of the site while logged in. If it is slow too, the cause is not particular to the dashboard.
Step 4: Read the slow screen in Query Monitor
Query Monitor is a plugin from the WordPress.org directory. It adds a menu to the admin toolbar, shown only to administrators by default, and everything in it is about the page load you are looking at. The toolbar shows four figures in order: page generation time in seconds, peak memory use, total time taken by database queries, and the number of queries.
Compare the first figure with the third. A screen that took 4 seconds to generate with 0.3 seconds of queries is not waiting on the database. Then open these panels:
- Queries by Component, under Queries, totals the queries and their time for each plugin, for the theme and for WordPress itself, sorted by time.
- HTTP API Calls lists the requests the server made to other servers while it built the screen, with the response code, the component responsible and the time each took.
- Hooks & Actions lists every action and filter that fired, with the plugin behind each callback. Filter it by component to see what one plugin attaches to dashboard screens.
- Timeline plots all of these along the length of the page load.
A red or orange highlight in the menu means PHP errors, and Query Monitor's documentation says warnings add time because each one is logged. How to read the debug log covers those. A screen that stops with an error and never loads is a different fault: see maximum execution time exceeded or allowed memory size exhausted.
The causes, in the order worth checking
1. A plugin that calls another server on every screen
License checks, update checks, news feeds and dashboard widgets all fetch something from another server. WordPress's HTTP API waits 5 seconds by default before it gives up on a request. Its handbook says it is generally a good idea to store what such a request returns. A plugin that does not store it asks on every screen, and you wait each time.
Confirm it. Open HTTP API Calls on a slow screen, then reload twice. A call that is there on every load is your lead. One that appears once and then stops was stored, which is how it should work.
On a staging copy you can prove it in one move. The first line adds a setting to wp-config.php that blocks WordPress's requests to other servers. Updates and license checks stop working while it is there, and Site Health reports "HTTP requests are blocked". Time the screen again, then run the second line to take the setting out.
wp config set WP_HTTP_BLOCK_EXTERNAL true --raw
wp config delete WP_HTTP_BLOCK_EXTERNALFix it. Look in the plugin's settings for the feature that makes the call, such as a news feed or a dashboard widget, and switch it off. Update the plugin and tell its author what you measured. Replace it if nothing changes.
Unticking a widget under Screen Options on the Dashboard is not enough. WordPress still runs a hidden widget's code and only hides the box. Switch the widget off in its plugin's settings, or have it removed in code with remove_meta_box(), as the handbook's page on dashboard widgets shows. WordPress's own "WordPress Events and News" widget fetches its feed after the page has arrived and keeps it for 12 hours, so it is not the cause.
2. Slow database queries
Confirm it. Query Monitor marks a query that takes longer than 0.05 seconds as slow and lists it under Slow Queries. Duplicate Queries shows the same query run many times in one load, which its documentation says often means a query inside a loop. Queries by Component shows which plugin the time belongs to.
Four things are worth looking for. The commands below only read, and they assume the table prefix is wp_.
Autoloaded options. Options marked to autoload are read on every page load. WordPress's performance guide advises keeping them under 800 KB in total. Since WordPress 6.6, Site Health reports a critical issue, "Autoloaded options could affect performance", above that size. This prints how many there are and their size in kilobytes:
wp db query "SELECT COUNT(*) AS options, ROUND(SUM(LENGTH(option_value)) / 1024) AS kb FROM wp_options WHERE autoload IN ('yes','on','auto','auto-on');"Queries on post meta. In WordPress's postmeta table the post ID and the meta key are indexed and the meta value is not. A query that searches or sorts by a meta value has to read through the rows, so it slows as the table grows.
A bloated postmeta table. This lists the 20 meta keys with the most rows. A key with far more rows than you have posts, or one left by a plugin you removed, is worth a question to that plugin's author.
wp db query "SELECT meta_key, COUNT(*) AS num_rows FROM wp_postmeta GROUP BY meta_key ORDER BY num_rows DESC LIMIT 20;"Revisions. Each one is a row in the posts table. This counts the rows of each type:
wp db query "SELECT post_type, COUNT(*) AS num_rows FROM wp_posts GROUP BY post_type ORDER BY num_rows DESC;"Fix it. The cleanup deletes, so it starts with a backup. How to clean up and optimize a WordPress database has the steps and says what each can do for speed. A slow query inside a plugin you need is for its author or a developer to change.
3. No persistent object cache
By default WordPress's object cache lasts for one request, so what it worked out for this screen is worked out again for the next. A persistent object cache keeps that data in memory between requests. WordPress's hosting handbook says it is particularly helpful where a page cannot be cached, such as for logged-in users, which describes the dashboard.
Confirm it. This prints Default when there is none:
wp cache typeSince WordPress 6.1, Site Health recommends one, on a live site, when the site is big enough to gain from it. By default that means more than 500 autoloaded options or more than 100,000 bytes of them, or 1,000 or more comments, options, posts, terms or users. The recommendation reads "You should use a persistent object cache".
Fix it. It needs a cache server such as Redis or Memcached, which is your host's to offer, and a plugin that connects WordPress to it. Ask the host first. An object cache does not shorten a call to another server.
4. PHP: the version, OPcache and workers
The version. WordPress recommends PHP 8.3 or greater, and says a site may be faster on a newer version because PHP becomes more efficient with each one. Site Health's Info tab shows "PHP version" in the Server section, and the end-of-life checker shows how long yours is supported. How to speed up WordPress has the safe order for changing it.
OPcache. PHP's manual says OPcache stores precompiled script bytecode in shared memory, so PHP does not have to load and parse scripts on each request. Every dashboard screen loads WordPress and every active plugin, so it matters here. The Server section shows "Opcode cache", "Opcode cache memory usage" and "Is the Opcode cache full?". Since WordPress 7.0 the Status tab also says when it is off: "Opcode cache is not enabled".
A full cache is the quieter problem. WordPress's hosting handbook says that when the cache runs out of memory or reaches its limit of scripts, a site spends more time recompiling. The settings are opcache.memory_consumption (128 megabytes by default) and opcache.max_accelerated_files (10000 by default).
Workers. Where PHP runs under PHP-FPM, its process manager, a setting called pm.max_children limits how many requests are served at the same time. A request that arrives when every process is busy waits for a free one. One person in the dashboard uses several: the screen, the Heartbeat, the editor's own requests, a second tab. A dashboard that is fast, then hangs, then is fast again, with nothing slow in Query Monitor, fits this.
What you can see yourself. Site Health, as above. wp cli info reports the PHP that the command line uses. WP-CLI's documentation notes that its php.ini is typically not the web server's, and OPcache is off for the command line by default, so trust Site Health for what the dashboard runs on.
What only the host can change. The number of workers and the OPcache settings. Ask how many PHP workers the plan has and whether the limit has been reached. PHP-FPM's status page records both: "listen queue" is the number of requests waiting for a free process, and "max children reached" says whether the limit has ever been hit.
5. The Heartbeat API and admin-ajax.php
The Heartbeat is a script on dashboard screens that sends a request to admin-ajax.php at a set interval. WordPress uses it to refresh the lock that stops two people editing one post, to refresh the editing screen's security tokens, to check that you are still logged in, and to autosave. Each request loads WordPress in full and takes a PHP process.
WordPress's handbook gives the interval as every 15 to 120 seconds. In the current script the default is 60 seconds, the block editor sets it to 10, and a window that is not in focus drops to 120.
Confirm it. In the Network panel, type admin-ajax into the Filter box and leave one screen open for a minute. A request with the action heartbeat is WordPress's own. Any other action name was chosen by a plugin. Count your open dashboard tabs as well, because each one sends its own.
Fix it. Close the tabs you are not using. To slow it down, WordPress's heartbeat_settings filter passes settings to the script, and the script accepts minimalInterval, which overrides any shorter interval. Create this file, and the mu-plugins folder if it is not there. WordPress loads every PHP file directly in that folder, and a file there is switched off only by removing it. A mistake in one can take the whole site down, so copy it exactly and be ready to delete it over SFTP.
<?php
// Have dashboard screens check in no more than once a minute.
add_filter( 'heartbeat_settings', function ( $settings ) {
$settings['minimalInterval'] = 60;
return $settings;
} );The script's own notes say a minimal interval above 120 seconds limits or switches off features such as post locks, which expire after 150 seconds. Switching the Heartbeat off altogether loses the lock, the token refresh and the warning that you have been logged out.
6. WP-Cron running while you work
WordPress checks its list of scheduled tasks on every page load, dashboard screens included. When one is due, it sends itself a separate request to run it, at most once every 60 seconds. That request does not hold up the screen you asked for. The task still runs on the same server and takes a PHP process, so a heavy one, such as a backup, slows every screen you open in the meantime.
Confirm it. This lists the tasks, with when each runs next and how often. Look for tasks that recur every few minutes, and for heavy ones timed for working hours.
wp cron event listFix it. WordPress's handbook documents the fix: have the server's own scheduler request wp-cron.php at a fixed interval, then add define( 'DISABLE_WP_CRON', true ); to wp-config.php. The order matters, because with the line in place and no cron job nothing scheduled runs. The guide to automatic backups has the steps under "Put WP-Cron on a real clock", and the page on missed schedules shows what a wrong order looks like.
7. Update checks: the Plugins and Updates screens
To check for updates, WordPress sends the list of installed plugins to api.wordpress.org and waits for the answer, for up to 3 seconds plus one more for every 10 plugins. How often depends on the screen. On the Updates screen it checks again if the last check is more than a minute old. On the Plugins screen, more than an hour old. Elsewhere, 12 hours. A plugin that is not hosted on WordPress.org can supply its own check through a documented filter, which means a request to its vendor's server.
Confirm it. Open HTTP API Calls on both screens and read the time against each address.
Fix it. If the slow call is to api.wordpress.org, look at Site Health: "Could not reach WordPress.org" is a critical issue there, and the server's connection is the host's to fix. If it is a vendor's server, tell the vendor. Remove the plugins and themes you do not use, so there is less to check.
8. The block editor
The editor can be slow in two places, so measure first.
- Slow to open or save. That is the server. WordPress's handbook says that when a post is saved, each active area of plugin panels (meta boxes) is submitted as a request of its own to
post.php. Read those requests in the Network panel. - Slow to type or select. That is your browser. The handbook says the editor's performance suffers as the number of rendered components grows, for example on long posts. Plugins add scripts and panels of their own. To find one, open the same post in troubleshooting mode, described below, and switch plugins on one at a time.
The editor also sends an autosave every 60 seconds by default. There is only ever one autosave per user for a post, so autosaves do not fill the database. On a slow server you can lengthen the gap:
define( 'AUTOSAVE_INTERVAL', 180 ); // Seconds9. Long list tables
The Posts, Pages, Comments and Users screens draw one row per item, and plugins add columns that can each run a query for every row. Duplicate Queries in Query Monitor shows this plainly.
Fix it. Open Screen Options at the top of the list and lower "Number of items per page:". Unticking a column there only hides it: WordPress still builds a hidden column for every row. Look for a setting in the plugin that added it.
A large number of users is handled for you: since WordPress 6.0, a site with more than 10,000 users no longer counts the users in each role on every load of the Users screen, which had been the slow query.
10. The host
When every screen is slow by a similar amount, at some hours more than others, and Query Monitor shows no single slow query or call, look at the plan. On shared hosting your account is held to limits. CloudLinux, server software used for this, documents what each one looks like. At the CPU or disk limit the site answers more slowly, with no error at all. At the limit on concurrent requests the visitor gets a 508 page, "Resource Limit Reached". At the memory or process limit, 500 or 503 errors.
Being slowed at a limit is called throttling, and WordPress cannot show it. The host's record of the account's usage can. Ask which limit the account reached and when. How to tell whether the fault is the host or the site has what to send them.
Which screen is slow, and the likely cause
| What is slow | Likely cause | Check first |
|---|---|---|
| Every screen, by about the same amount | A call to another server on every load, large autoloaded options, no object cache, PHP | HTTP API Calls, then Site Health |
| Every screen, at certain hours | The plan's limits, or a scheduled task running | wp cron event list, then the host |
| Fast, then hangs, then fast | Every PHP worker busy | Open tabs and the Heartbeat, then the host |
| The Dashboard screen only | A widget | Query Monitor on that screen |
| Plugins and Updates | Update checks | HTTP API Calls |
| Posts, Pages or Users lists | Rows per page, a plugin's columns, queries on post meta | Duplicate Queries and Slow Queries |
| The editor, opening or saving | Plugin panels, the server | The Network panel while saving |
| The editor, typing | The browser: a long post or a plugin's editor script | Troubleshooting mode |
| One plugin's own screens | That plugin | Queries by Component, then its author |
When nothing shows: find it by elimination
Step 1: Work on a staging copy, or in troubleshooting mode
Switching plugins off on the live site changes it for visitors. Either set up a staging copy, or use the Health Check & Troubleshooting plugin from the WordPress.org directory. Its troubleshooting mode gives you a clean session with every plugin off and a default theme, for your user only, until you switch it off or log out. Go to Tools, then Site Health, open the Troubleshooting tab and select "Enable Troubleshooting Mode". A menu in the admin bar then switches plugins back on one at a time. Must-use plugins stay on.
Step 2: Time the slow screen with everything off
If it is fast now, a plugin or the theme is the cause. If it is still slow, it is the server: go back to PHP, the object cache and the host.
Step 3: Switch plugins on in halves
Switch half on and time the screen. If it is slow, the cause is in that half. If not, it is in the other. Halve again until one is left, then confirm it by switching that one off with all the others on. How to find a plugin conflict has the method in full.
What not to do
- Do not delete database rows without a backup. A delete cannot be undone. Export first, to a file outside the folder the site is served from:
wp db export ~/before-cleanup.sql. - Do not install several "optimizer" plugins at once. You will not know which one changed what, and each is more code on every screen. A page cache plugin does nothing for the dashboard, which is never cached.
- Do not switch the Heartbeat off, or add
DISABLE_WP_CRONwith no cron job in place. The first costs you post locks. The second stops scheduled posts, backups and update checks. - Do not change several things between measurements. One change, then time the same screen.
When to get help
Rewriting a slow query, changing how a plugin calls another service and tuning PHP are a developer's work, and the server's settings are the host's. Our speed optimization service is a one-time job on a WordPress site that has become slow: we measure before the work and again after it, so you can see what changed.
Common questions
Will a caching plugin speed up the dashboard?
A page cache will not, because the dashboard and logged-in users are left out of it. A persistent object cache can, because it keeps the results of database work in memory between requests. It needs a cache server from your host.
Is it safe to disable the Heartbeat API?
Slow it down and keep it on. WordPress uses it to hold the lock on a post you are editing, to refresh the editing screen's security tokens and to warn you when you have been logged out. An interval of up to 120 seconds keeps those working.
Do too many plugins make the admin slow?
What each plugin does matters more than how many there are. One plugin that calls another server on every screen can cost more than twenty that do little. Query Monitor's Queries by Component and HTTP API Calls panels show which ones cost time on the screen you are looking at.
How fast should the dashboard be?
WordPress publishes no target for dashboard screens. For comparison, Site Health treats a server response under 600 milliseconds as acceptable for the front of the site, and Query Monitor marks a single database query as slow above 0.05 seconds. Your own before and after figures on the same screen are the measure that matters.
- Cost guideWordPress speed optimization cost: what the job is, what it should include and what moves the price
- Guideadmin-ajax.php high CPU usage in WordPress: how to find what is calling it
- GuideAI bots slowing down your website: how to confirm it on WordPress and what to do, mildest first
- GuideHow to clean up and optimize a WordPress database, and what it does for speed
- GuideHow to enable gzip and Brotli compression in WordPress
- GuideHow to fix Cumulative Layout Shift (CLS) in WordPress: find what moves and reserve its space

