Most Common Cause of a Slow WordPress  Admin

Why is your WordPress admin so slow? It's probably HTTP API requests made by premium plugins.

A slow WordPress admin is the worst, it can significantly reduce publishing productivity, and it’s a big pain for anyone that works in the admin frequently. It can be caused by many things, but the most common and least discussed seems to be slow HTTP API responses from premium or paid plugins that require a license key. When your site has paid or premium plugins that require a license and a very slow admin, the API calls made by these plugins are most likely the source of the problem.

Both free and premium plugins make API requests, but free ones make all of their requests to api.wordpress.org, which is built to handle an extremely high volume of traffic. Premium plugins make similar requests to their own servers, which may or may not be configured to handle the volume of traffic they receive.

These HTTP requests allow premium plugins to check for updates or verify a license key is valid. The responses are often cached using the Transients API provided by WordPress, but it’s common to see very short cache expiration times, such as 5 minutes.

And when they’re slow, they slow down everything.

Identify The Issue

Check if your premium plugins are causing a slow WordPress admin using the following steps:

  1. Install and activate the Query Monitor plugin
  2. Perform an action in your sites /wp-admin/ area that’s commonly slow. Keep trying various actions until you experience a slow load.
  3. Click the button/link in your admin toolbar that looks similar to this: 0.00s 0.0MB 0.02s 45q
  4. The Query Monitor console will open at the bottom of your screen
  5. Click the HTTP API Calls menu option on the left

If there are no results, then the cause is likely something other than an HTTP API. I suggest reading the Other Common Causes section below for next steps.

If you do see results, then it’s time to analyze them and determine if any are problematic. Look for any rows in the table with a high value in the Time column. Anything over 1-2 secs is very slow, and would likely be the cause of your trouble.

Quick Ways to Fix It

Once you’ve identified that HTTP API calls are the source of your problem, you can choose the best way to fix it.

Option 2: Disable External API Requests (whitelist)

WordPress provides a WP_HTTP_BLOCK_EXTERNAL constant configuration option that you can add to your wp-config.php file to control HTTP API requests using a whitelist approach. When set to true your WordPress site will block any external API requests made with the wp_remote_request or WP_Http class.

define( 'WP_HTTP_BLOCK_EXTERNAL', true );

Enabling just this rule will block your sites’ ability to connect to api.wordpress.org, which is where plugins are downloaded from. To avoid this issue, you’ll need to add the WP_ACCESSIBLE_HOSTS constant as well, which will allow you to whitelist certain allowed hosts.

If you plan on only using free plugins, then this is a good value to use:

define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,*.github.com' );

If you do use premium plugins than it’s not a good option. When one of these plugins needs to confirm your license is valid, it will fail and likely cause a broken page.

Option 2: Block Specific API Requests (blacklist)

Instead of specifying what’s allowed, it’s usually better to specify what’s not allowed using a blacklist approach. This approach allows requests anywhere, except for hosts that you specifically want to avoid.

/**
 * Bypass Slow HTTP API Requests
 *
 * Skip external API requests made by premium plugins to speed up
 * the WordPress admin experience significantly.
 *
 * @param mixed $preempt
 * @param mixed $parsed_args
 * @param mixed $url
 */
function kevinlearynet_filter_slow_http_requests($preempt, $parsed_args, $url)
{
  $request_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null;
  $request = parse_url(site_url($request_uri));
  $path = isset($request['path']) ? $request['path'] : null;
  $page = isset($_GET['page']) ? $_GET['page'] : null;

  // Allow HTTP requests on certain pages to avoid issues with plugin functionality
  // that requires external API calls for verification
  $allowed_on = [
    '/wp-admin/tools.php',
    '/wp-admin/update-core.php',
    '/wp-admin/update.php',
    '/wp-admin/upgrade-functions.php',
    '/wp-admin/upgrade.php',
    '/wp-admin/plugin-install.php',
    '/wp-admin/plugins.php',
    '/wp-admin/options.php',
    '/wp-admin/admin.php',
  ];
  if (in_array($path, $allowed_on)) {
    return false;
  }

  // Special cases
  if (strstr($request_uri, 'acf-') && strstr($url, 'connect.advancedcustomfields.com')) {
    return false;
  }

  // Block HTTP API requests everywhere else when the request
  // URL matches an item in the blacklist
  $blacklist = [
    'connect.advancedcustomfields.com',
    'www.relevanssi.com',
    'rankmath.com',
    'wistia',
    'translationspress.com',
    'cloudfront.net',
    'my.elementor.com',
    'packages.translationspress.com',
    'wpdeveloper.net',
    'api.deliciousbrains.com',
  ];

  foreach ($blacklist as $host) {
    if (strstr($url, $host)) {
      return new WP_Error('bypass', "Premium plugin remote API requests are disabled because they're way too slow.");
    }
  }

  return false;
}
add_filter('pre_http_request', 'kevinlearynet_filter_slow_http_requests', 99, 3);

This makes use of the pre_http_request filter that’s set inside class-wp-http.php (GitHub reference). When the hooked function returns false a normal HTTP request is handled as if no filter existed at all. But when you return anything other than false, the value is returned as the response from the external API.

Using this filter hook can effectively disable specific API’s based on the URL or the HTTP request arguments. In the example above, I’m blocking API calls made by the Migrate DB Pro plugin, which I’ve found to be extremely slow lately. Swap out api.deliciousbrains.com in my example with the hostname of the API you’ve found to be slow. Drop this function into your theme’s functions.php file, and you should see an immediate improvement in the speed of your WordPress admin pages.

Of the two approaches here, I find this approach the best. Once I’ve determined the API’s that are slow, I can exclude only them and avoid any unexpected issues with other uses of other remote requests using wp_remote_* functions.

Other Common Causes

If HTTP API calls aren’t the cause of your slow WordPress admin, then I’d suggest looking into the following next:

Slow or Excessive Queries

Hefty page builders like Elementor or one-size-fits-all themes like Avada make excessive amounts of queries to your database. If you’re the only one working in your WordPress site’s admin area at any given time, and you have a relatively low volume site, it’s not a problem. If you have a high volume site, especially one that makes frequent POST requests like a WooCommerce site for example, then this may be the source of your slow WordPress admin area.

You can use the Query Monitor plugin to check if this is your problem:

  1. Perform an action in your sites /wp-admin/ area that’s commonly slow. Keep trying various actions until you experience a slow load.
  2. Click the button/link in your admin toolbar that looks similar to this: 0.00s 0.0MB 0.02s 45q
  3. The Query Monitor console will open at the bottom of your screen
  4. Click the Queries menu item on the left

In the table that appears, sort by the Time column and look for any value higher than 0.1s. This could be the cause, depending on how many queries the page had made. 0.1s may not seem high, but if that query occurs on ever admin pageview it can trigger issues with database locking when multiple people are using the admin. Database locking will hold up requests made to the same database table. If 5 people are working inside of WordPress at the same time, it could easily turn a 0.1s query into a 1+ second query.

Memory Usage

If your system is low on memory, or the amount available to PHP and WordPress is too low, it could cause performance issues with your site. It’s not likely the cause of a hanging page, because you’d probably receive the following PHP fatal error at some point:

PHP Fatal Error: Allowed Memory Size Exhausted

If you think this could be the issue, check your PHP error logs for this fatal error. If you do see any occurrences of this error, take a look at the Peak Memory Usage statistic on the Overview section of Query Monitor while you’re in the WordPress admin area. It will tell you the % of memory currently used by WordPress, the maximum allowed by WordPress, and the amount available to PHP on your web server.

It looks something like this:

  • 11,739,448 bytes (11.2 MB)
  • 2.2% of 512 MB WordPress limit
  • 1.1% of 1,024 MB server limit

These values can be adjusted depending on how much your server has available, which will help you improve performance.

Less Common Possibilities

There are other possible causes, but they’re less likely to be the problem in most cases. This is especially true if you’re using a WordPress specialized host like WPEngine or Kinsta. Here’s a list if you need to explore other possibilities:

  • Issues with an upstream reverse proxy
  • Out of date WordPress install, theme or plugin(s)
  • Extremely large database
  • Unoptimized database tables, or overly large records (usually in the wp_options table)
  • Low disk space
  • Database locking
  • Stressed web server
  • Incorrectly tuned PHP-FPM or nginx server
  • Latency issues with your server’s DNS configuration and handling

Meet the Author

Kevin Leary, WordPress Consultant

I'm a freelance web developer and WordPress consultant in Boston, MA with 17 years of experience building websites and applications. View a portfolio of my work or request an estimate for your next project.