Why is my WordPress dashboard so slow?

Speedy WordPress dashboard

One of my clients noted that their WordPress dashboard now took several seconds to load. Since they publish several posts a day, the slow load times were seriously interfering with their workflow.

My client's blog has been around for about two decades and has an active reader community. It's active enough that the site's database now holds more than a million non-spam comments.

The problem was tricky to diagnose at first. Everything worked fine on both our staging server and my local copy. One diagnostic plugin and a WordPress hook later, their dashboard loads quickly once again.

Diagnosing the issue

Perhaps the best tool for diagnosing and debugging WordPress is John Blackbourn's Query Monitor plugin. As its name suggests, Query Monitor tracks database queries and reports which ones are especially slow.

Query Monitor showed which query was choking the dashboard: the comment count query. This query retrieves the number of new comments awaiting review, which is displayed as a blue circle in the admin menu.

WordPress menu's new comment count. It's a circle with a blue background and white foreground text.

Here's the query:

SELECT COUNT(*)
FROM wp_comments
WHERE ( comment_approved = '1' )
AND comment_type NOT IN ('note')

This query searches through all comments in the database and returns how many aren't of the note type. With a few hundred thousand comments in the database, it executes in a few milliseconds. With more than a million comments, it takes 2 to 3 seconds.

It ran fine on the staging server and on my laptop because both use a smaller, separate database. In production, though, my client's WordPress dashboard experienced frequent timeouts and severe slowness.

How to fix it

Fortunately, WordPress offers a way to prevent this query from running. Use the wp_count_comments hook to filter the output of the wp_count_comments() function.

add_filter('wp_count_comments', 'disable_admin_menu_comment_count', 10, 2);
function disable_admin_menu_comment_count($count, $post_id = 0) {
  if (is_admin()) {
      return [
          'approved'            => 0,
          'moderated'           => 0,
          'spam'                => 0,
          'trash'               => 0,
          'post-trashed'        => 0,
          'total_comments'      => 0,
          'all'                 => 0,
      ];
  }
  return $count;
}

This prevents the comment count query from running on the dashboard and other admin screens. Downside: you'll need to proactively check the comments queue for new entries to moderate.

Creating a plugin is the best way to deploy these filters and actions. Add it to your site's must-use plugins folder (wp-content/mu-plugins) so it can't be accidentally deactivated or deleted.

Subscribe to the Webinista (Not) Weekly

A mix of tech, business, culture, and a smidge of humble bragging. I send it sporadically, but no more than twice per month.

View old newsletters