Caching with transient options and API in wordpress

from the transiants api codex page:

… offers a simple and standardized way of storing cached data in the database temporarily by giving it a custom name and a timeframe after which it will expire and be deleted

One usage pattern for the transient API is to cache values you retrieve from a remote server. The overhead of establishing a connection to the remote server, sending a query and waiting for a reply is too big so we make a concession and instead of been totally up to date with our info, but with a site that take ages to load, we better be 5 minutes late with the info, but with usable site, and we will do it by caching the last result for 5 minutes in a transient option.

So instead of having

echo get_my_latest_video_from_youtube();

We can use

$video = get_transient('latestvideo'); // we might have the value already in our cache, lets retrieve it
if ($video) { // it is there
echo $video;
} else { // nothing in the cache, or the cache had expired
$video =  get_my_latest_video_from_youtube(); // get the video code
set_transient('latestvideo',$video,5*60); // set the cache with expiry set to 5 minutes in the future
echo $video;
}

The nice thing about this code is its robustness as it will recover from any event that hurt the cache and regenerate the info.

Important to note that this solution does not eliminate entirely the delay in site load caused by accessing the remote data, it just make it less frequent. For a site which has only 1 visitor every 5 minutes or more we basically haven’t changed anything as the cache will expire before the next visitor will come. Setting longer expiration interval gives you more performance value, so you should set it as long as possible without making the displayed data to be stupidly out of date.

But what can be done if we want that all of our users will have great experience, not only 99% of the time, but 100% of the time? If our interval is long enough we can pre populate the cache with a scheduled backend operation.

The next code assumes your interval is 5 hours

wp_schedule_event(time(),'hourly','regenerate_video'); // since we want to the avoid the situation in which the cache expires we have to use a schedule which is smaller then 5 hours. This should really be done only on plugin or theme activation

add_action('regenerate_video',regenerate_video);

function regenerate_video() {
$video =  get_my_latest_video_from_youtube(); // get the video code
set_transient('latestvideo',$video,5*60*60);
}

This way we prime the cache every hour and therefor every user gets a current enough info. But then the cache practically never expires couldn’t we get the same results by using the usual options api aand store the cached value as an option? Our code will then look like

// on front end
$video = get_option('latestvideo');
if (!$video) {
regenerat_video();
$video = get_option('latestvideo');
}
echo $video;

// on the backend
wp_schedule_event(time(),'hourly','regenerate_video'); // since we want to the avoid the situation in which the cache expires we have to use a schedule which is smaller then 5 hours. This should really be done only on plugin or theme activation

add_action('regenerate_video',regenerate_video);

function regenerate_video() {
$video =  get_my_latest_video_from_youtube(); // get the video code
update_option('latestvideo',$video);
}

What we have done here is to practically change the expiry mechanism. Now we can control better when the data expires.

So which pattern is better, transients or straight options? There is another factor you need to take into account before deciding about that – the existence of object catching in the site.
Unlike options, transients do not autoload into memory when WordPress starts up. This means that if there is no active object cache on the site, get_transient actually performs an extra SB query, and there is nothing worse for performance then a DB query that can be avoided, especially when this query is happening on the front end.

On the other hand, when object caching is active, transients are not stored to the DB at all, but only at the cache. This eliminates the cost of using get_transient and make the options table smaller and therefor each operation (add,change,delete,query) on it faster.

 

Leave a Reply

Your email address will not be published. Required fields are marked *