Increasing WordPress REST API performance

Recently, we built a piece of search as you type (often abbreviated “SAYT”) functionality for a client’s e-Commerce site.

Although the frontend performance of the website is fast, we noticed a lag while typing into the SAYT interface. The site uses WooCommerce, WooCommerce Bookings and Yoast SEO, three well written but complex WordPress plugins. A little testing showed that disabling them improved performance significantly; clearly not a viable solution. We also considered moving the “backend” of the SAYT functionality away from WordPress to a separate piece of code but despite the data being stored in a separate database table we were using a lot of WordPress functionality such as the REST API and transients which would have taken significant work to replicate.

Not loading the plugins for REST requests seemed like the obvious answer – but this broke too much functionality elsewhere. So, we developed a small plugin which speeds up the WordPress REST API by selectively loading WordPress plugins based on the namespace being called. On the site in question, this reduced the response time from the SAYT backend from 320ms to 30ms, and resulted in a significant reduction in server load.

Introducing QuickREST

We’ve called the plugin QuickREST and made it available for other developers on our GitHub page.

Although the plugin does work “out of the box” if it is installed as a Must Use plugin (which it must be to load before other plugins), the default behaviour is to skip all plugins for REST requests which is probably undesirable, but it can be controlled by a filter (the filter also needs to be added via Must Use plugin so it is available before the other plugins are loaded:


function my_plugin_map_function( $map ) {
$new_map = [
'wc' => [ 'woocommerce/woocommerce.php' ],
'wc-analytics' => [ 'woocommerce/woocommerce.php' ],
'yoast' => [ 'wordpress-seo/wp-seo.php', 'woocommerce/woocommerce.php' ],

];
return array_merge_recursive( $map, $new_map );
}
add_filter( ‘quickrest_plugin_map’, ‘my_plugin_map_function’, 15, 1 );

Developers can also supply an special namespace called _default which as the name suggests allows you to specify a list of plugins which should be loaded by default, you can also use this to change the default behaviour so that all plugins are loaded by default.


add_filter(
'quickrest_plugin_map',
function( $map ) {
// Remove our filter so we don't get stuck in a loop when getting the active_plugins option.
remove_filter( 'option_active_plugins', 'quickrest_filter_plugins', PHP_INT_MAX - 1 );
$new_map = [
'_default' => get_option( 'active_plugins' ),
];
add_filter( 'option_active_plugins', 'quickrest_filter_plugins', PHP_INT_MAX - 1 );
return array_merge_recursive( $map, $new_map );
},
10,
1
);