Optimizing default WordPress REST API user endpoint for redundant DB calls made for permissions check.

person holding turned on silver laptop computer
Photo by Pixabay on Pexels.com

While working with one of our client at rtCamp who was using REST API for thier website with PWA theme, We found out that it was taking way too much time at user endpoint wp/v2/users/{id}

Upon investigation I found out that on server dispatch it goes under permission check with permission_callback per item with following SQL query hitting db several times based on per page items.

SELECT COUNT(*) FROM wp_posts WHERE ( ( post_type = 'post' AND ( post_status = 'publish' ) ) OR ( post_type = 'page' AND ( post_status = 'publish' ) ) OR ( post_type = 'attachment' AND ( post_status = 'publish' ) ) OR ( post_type = 'custom_post_0' AND ( post_status = 'publish' ) ) OR ( post_type = 'custom_post_1' AND ( post_status = 'publish' ) ) OR ( post_type = 'custom_post_2' AND ( post_status = 'publish' ) ) OR ( post_type = 'custom_post_3' AND ( post_status = 'publish' ) ) OR ( post_type = 'custom_post_4' AND ( post_status = 'publish' ) ) ) AND post_author = {id} 

As you can see in snippet below it’s calling for

`permission_callback` => array( $this, 'get_items_permission_callback' )

https://gist.github.com/milindmore22/2b830f2dd3120670d2b4dc1587b6f242

which has count_user_posts call which is uncached and hits DB every time.

I have worked on few WordPress VIP projects for same reasons I configured My editor ( Netbeans ) to check for WP coding Standards it gives me warning about count_users_posts and asked me to use wpcom_vip_count_user_posts instead because count_users_posts uncached.

So I have to make it’s result cached somehow,

Firstly I Google ( don’t judge me everybody does it. 😀 ) for some solution but found nothing even on 4th search page thats deep web for me .

No help came from stackoverflow which was my only hope that day.

I searched WordPress core trac there is ticket for same  #39242,

finally after some debugging, I decided to replace permission_callback for wp/v2/users/{id} route with cached function with custom code as follows.

https://gist.github.com/milindmore22/b9db3db1a9273c97fc5bcd1d4b4632a5

The Cached permission callback is similar function as core with only one twist different callback for user post count 😀

https://gist.github.com/milindmore22/44f208d5773bf059f0e6491e942979fe

The cached_count_users_posts function is clone of WordPress VIP function wpcom_vip_count_user_posts

https://gist.github.com/milindmore22/7472fd107299325d513e7996cd612e47

This will offload your DB hits, it’s will very helpful while handling heavy weight WordPress sites, until that core ticket is answered and closed, I will try to contribute on that core ticket and that should be our the long term plan.

here is full code My Friend, Hope this helps you.

https://gist.github.com/milindmore22/e1cf135b550b0caf210b74c3eeb6f431

Did you do things differently please let me know in comments ?