admin-ajax.php high CPU problem solved

I have to admit I am obsessed with web performance, and I spend a lot of time analysing server-side performance graphs. Recently I noticed a significant spike in database CPU usage as well as the web server CPU usage on one of my many websites. Almost all of my websites are on WordPress 3.7.1 (at the time of this writing), Linux, Nginx and PHP-FPM stack. After looking at Newrelic graphs, it was clear to me that I was dealing with admin-ajax.php high CPU problem. Here are a couple of graphs to support my case. The first one is server response time from Newrelic and the second one is the high CPU consumption graph.

admin-ajax.php high CPU - newrelic graph

Server response graph showing the raise in server response time

admin-ajax.php high CPU - AWS RDS graph

MySQL CPU utilisation graph clearly shows admin-ajax.php high CPU problem

There was also a 3rd graph that showed me admin-ajax.php was the clear offender. I forgot to take a screenshot of that.

admin-ajax.php high CPU – Problem

Now how could this happen?  First of all you need to understand what admin-ajax.php does and what it’s used for. admin-ajax.php is part of WordPress AJAX API that is used in the backend and frontend. WordPress heartbeat API also calls this script every 15 seconds to auto save your posts while you’re editing your posts.  It also calls it on various other pages while you’re logged in to provide you with information like – what your fellow administrators and authors are currently working on. There are other things that the heartbeat API will do as well. Now imagine if you have many contributors and administrators logged into the backend, with each session sending heartbeat API requests to the server every 15 seconds.  This could cause some performance problems to your WordPress installation and admin-ajax.php high CPU problem is directly related to this.  I don’t know why this hasn’t been optimised a little better by the WordPress team, but the graphs above clearly indicate that this is a problem.  I’m sure they are aware of this issue and hopefully there will be a better solution. Perhaps WebRTC could come to the rescue??

admin-ajax.php high CPU – Solution

The interim solution is to simply disable the WordPress heartbeat in your backend, but still allow it to autosave your posts. Autosaving is a very nice and important feature especially if you don’t fancy losing your precious work!  Thanks to this thread the solution worked well and you can see from the DB graph above, the CPU consumption dropped back down considerably after disabling the WordPress heartbeat.

add_action( 'init', 'my_deregister_heartbeat', 1 );
function my_deregister_heartbeat() {
	global $pagenow;

	if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow )
		wp_deregister_script('heartbeat');
}

Of course, there are other instances where your admin-ajax.php high CPU problem can manifest itself. For example, if you are using a 3rd party plugin that has some sort of ajax functionality. For example, plugins that fire up modal popups on every page load?  That will most certainly hammer admin-ajax.php script in the backend and cause instabilities to your application.  There are some awesome caching plugins out there, but none of them will and shouldn’t cache admin-ajax.php requests since the script is located in wp-admin directory. It’s good to be aware of this.

Have you had any issues with admin-ajax.php?

Marko