Comparing WordPress REST API Performance to admin-ajax.php

db-BenchmarkingRESTApi

Since the introduction of the WordPress REST API, many plugin developers have started converting their plugins to use the REST API instead of the older AJAX API (admin-ajax.php). Aside from the REST API simply being newer technology, rumor has it that the REST API is also faster and more reliable than the older endpoints due to the fact that not as much of WordPress is loaded during a typical REST request.

In this article, we’ll be looking at the life of a typical REST request as well as a similar request made over admin-ajax.php to see how they compare.

The Life of an admin-ajax.php Request

Let’s start by breaking down what happens when we make a typical AJAX request to admin-ajax.php. When your browser makes a request to that file, it loads a few other core WordPress files in order to be able to serve the request with core functions loaded:

/wp-load.php
/wp-config.php
/wp-settings.php (which loads most core files, all active plugins and themes, and the REST API)
/wp-admin/admin.php
/wp-admin/includes/ajax-actions.php

After loading these files, WordPress calls the admin_init hook, which several core functions hook into. The below core functions were called on this hook in WordPress 4.5.3:

register_admin_color_schemes
send_frame_options_header
_wp_check_for_scheduled_split_terms
_wp_admin_bar_init
_maybe_update_core
_maybe_update_plugins
_maybe_update_themes

After these functions have been called, WordPress finally calls the AJAX action provided in the $_GET[‘action’] or $_POST[‘action’] variable.

The Life of a REST API Request

Compared to the admin-ajax.php request, the typical REST request looks slightly different. Since the REST endpoints are handled by the WordPress Rewrite API, the request is passed to /index.php, which then loads the rest of WordPress normally.

/index.php
/wp-blog-header.php
/wp-load.php
/wp-config.php
/wp-settings.php (which loads most core files, all active plugins and themes, and the REST API)

Unlike requests sent over admin-ajax.php, the REST API doesn’t load the WordPress admin section via /wp-admin/admin.php, nor does it fire the admin_init action hook. Based on that, it’s likely that any plugins or themes that don’t rely on admin-specific functionality – but are using admin-ajax.php – should see a slight performance boost by switching over to the REST API.

The Benchmarks

Now that we’ve seen a bit of what happens behind the scenes, let’s set up a scenario that can be easily benchmarked. To do this, we’re going to create a simple function that can be run on either admin-ajax.php or over the REST API:

function benchmark_request() {
    $result = array( 'time' => time() );
    echo json_encode( $result );
    exit;
}

add_action( 'wp_ajax_benchmark_request', 'benchmark_request' );
add_action( 'rest_api_init', function() {
    register_rest_route( 'benchmark/v1', '/benchmark/', array(
        'methods'  => 'POST',
        'callback' => 'benchmark_request'
   ) );
} );

The above function just returns the time in JSON – this just helps make it easier to see that the requests aren’t being cached.

To perform the actual benchmarking, we’re going to be using ApacheBench, a command line benchmarking tool that allows you to fire off multiple requests at once to get a feel for how the server is performing.

Let’s test the admin-ajax.php version first.

 ab -n 100 -c 1 -p ~/Desktop/post.data -g ~/Desktop/ajax.tsv -T application/x-www-form-urlencoded http://localhost/rest-api/wp-admin/admin-ajax.php

The above command sends 100 POST requests to the /wp-admin/admin-ajax.php file and logs the response times. The post.data file referenced is simply a text file containing the URL encoded $_POST values to be sent with the request (in this case, action=benchmark_request).

ajax

With 100 requests, the average response time was 253ms on a fresh install of WordPress on MAMP and PHP 7 with no other plugins activated. This gives a good baseline for the same test over the REST API:

ab -n 100 -c 1 -p ~/Desktop/post.data -g ~/Desktop/rest.tsv -T application/x-www-form-urlencoded http://localhost/rest-api/wp-json/benchmark/v1/benchmark/

rest

Not surprisingly, the REST API is slightly faster in this comparison, with an average response time of 217ms over 100 requests. This obviously isn’t a huge difference, with the REST API only being about 15% faster than the traditional AJAX API, but over many requests this small difference can definitely add up, especially as more plugins are added.

Let’s run the same benchmarks but with a few plugins activated. For these tests I activated a few common plugins that you might find on a typical website:

  • ACF
  • Akismet
  • Black Studio TinyMCE Widget
  • WP Migrate DB
  • WP Super Cache
  • Yoast SEO

Despite the increase in overall response time, the performance gap between admin-ajax.php and the REST API remains about the same. With the additional plugins loaded, the REST API was about 16% faster, and had an average response time of 490ms compared to 567ms over admin-ajax.php:

ajax-plugins

rest-plugins

A website with a larger number of plugins could see an even larger performance increase from the REST API, but that depends completely on which plugins are running and how they are coded.

So Should You Use the WordPress REST API?

From a performance standpoint, it’s clear that there is a slight advantage. Adding custom API endpoints is incredibly easy, and since it doesn’t have to load as much of WordPress core (including the admin area and the commonly-used admin_init hook), it will likely be faster than using admin-ajax.php in most cases.

In terms of reliability, the REST API still depends on the quality and integrity of the active plugins or themes. A poorly coded plugin could still easily interfere with REST requests, especially as more plugins adopt the REST API in the future. However since there are less plugins using the REST API, it should be slightly more reliable for now.

Overall, it’s definitely a good idea to at least consider using the REST API. Adding custom API endpoints is incredibly easy, and it doesn’t take much to switch over existing code either.

Have you converted anything over to the REST API yet? Did you see a similar performance increase? Let us know in the comments below.

About the Author

Matt Shaw

Matt is a WordPress plugin developer located near Philadelphia, PA. He loves to create awesome new tools with PHP, Javascript, and whatever else he happens to get his hands on.

  • Rita

    I used both extensively over the last few month and am now in strong favor of the WP API – our own benchmarks show a much more divided picture: in one instance we could not bring admin-ajax to under 1s which went to 100ms when switching to wp-api. I guess it depends what your admin set up is doing on load…

  • darrencooney

    Nice article, Matt – While I was building the REST API add-on ( https://connekthq.com/plugins/ajax-load-more/add-ons/rest-api/ ) for Ajax Load More I also found that using the REST API vs admin-ajax.php is definitely a winner in terms of performance. So much so that depending on the server I was testing on I could get the performance increase up to almost 25%.

    And as you said, setting up your own endpoint is so simple it really makes sense to just dive right in.

    • Anon

      Can you just simply create a custom endpoint and pull the same data? How is that faster as compared to using default REST APi?

      • Daniel Iser

        Check out how we handle it in Popup Maker. Ours works with admin-ajax and switches to the Rest API when its available. IE backward compatible. But the answer to your question is yes, we use the same internal handlers for either method and do a little magic to convert the data in our JS when needed.

        PHP Handlers: https://github.com/PopupMaker/Popup-Maker/blob/master/includes/modules/analytics.php

        JS that shows how to build a dynamic request: https://github.com/PopupMaker/Popup-Maker/blob/master/assets/js/src/site/plugins/pum-analytics.js

        And for your $.ajax functions .success/.done callback do this:

        .done(function (response) {
        var data = rest_enabled ? response : true === response.success ? response.data : false;

        // Now data can be used reliably
        forms.handler($form, data);
        })

        Also of note, this is how we pass in the pum_vars.restapi from the top of the JS: https://github.com/PopupMaker/Popup-Maker/blob/master/includes/scripts.php#L40-L41

        Hope that helps everyone. We are using this approach in several plugins, but Popup Maker has 100k+ installs so you can see its reliable enough.

        That all said I would also be interested to see the comparison between admin-ajax vs rest-api vs custom handler. I have found a few situations in a forum plugin I’ve been working on where the rest-api comes out consistently slower VVV installs. Both call the same handlers so the stuff under our hood is the same, but haven’t determined why admin-ajax could ever be faster, but it is constantly for specific tasks such as pagination of topics & ajax load more.

  • How is REST API performance vs hooking into ‘init’ action with a custom request handler? Thats what most folks do due to admin-ajax.php being slow.

    • I’d be interested to see this added to the comparison as well. 🙂

      Also for those reading that need raw speed (on their own sites), a few years back I built a little library that lets you selective enable plugins for specific endpoints: plugin-endpoints.

      • Dan Smart

        Great plugin – thanks for the share.

    • Jon

      +1, would love to see admin-ajax vs REST API vs _custom handler_

  • Dan Smart

    Great article, anything that can speed up AJAX requests is essential.

  • Nice article for sure been using a custom admin ajax plugin that basically does what WP REST API.

    On a project that needed to work with gravityforms, stream data from a custom 3rd party api, and also pull dynamic data from the localhost database. This all had to populate several variable/conditional dropdown options and data fields. It was essential allowed to merge two calls into a single endpoint while retaining security.

    Noticed load times on the already blazing fast EC2 system but time to populate and compile was bottle necking on the remote api. RESTed assured it was working awesome.

  • Basilakis

    Interested reading.

    Question: How much faster whould be, to load a list of posts ( lets say 10 ) with WP_QUERY and how much faster if loaded with AJAX and the Rest API?

    That is also an idea, so we can see some nice metrics 🙂

  • Jahnu Gogoi

    Nice article. I made one desktop app in c# for client and rest api with oauth at server to manage multiple wordpress sites with features like bulk media, post, pages upload. it’s been blazing fast using rest api. i have tested uploading 100 posts together which takes less than a minute and i think it’s barely impossible even with wordpress backend.

  • what about dev-time, more flexible and controlled rest-api endpoints?

    I Couldn’t help but notice in this example it’s 1-line vs 6-lines (which I get is nothing for those with a good snippet lib); but having looked into WooCommerce API, I’ve also seen how large rest requests with lots of rules can be compared to simpler methods I’ve seen using `admin-ajax.php`

  • Wish some of the plugins I have installed would convert to RestAPI

  • Ilan Diamond

    Thanks love your articles !
    What about REST API via admin-ajax from the theme side –
    for example sending form data to server
    Would you still recommend using REST API ?

  • In Philly

    The WooCommerce REST Api is the slowest thing in the world, and I can’t find any help online as to how to make it respond more quickly. Any suggestions would be greatly appreciated.