Put Your WordPress Code Into Hyper Drive With Transients
The word “transient” is defined as “lasting only for a short time”. WordPress uses the term to describe bits of data that are stored in cache for a short time. Before I show you how this happens let’s talk about why you would want to do this.
Why micro cache?
When writing code, there are some processes that simply take a relatively long time. By “long time” I mean more than 1 second, possibly up to 5 or 10 seconds. In WordPress this is very common with complex queries, usually involving meta fields.
Another very common scenario is making a request to a remote API. The HTTP query itself can take 1-2 seconds, and if the remote server is slow you can easily get to 5 or 10 seconds. Then when you get the data back you have to process it. If you’re doing this in PHP then it can make the entire page load slowly. If you’re using Javascript to make a call to your own server where PHP is doing the remote request it can make your page load in a haphazard way and look terrible.
Transients provide a way to take those long queries and save the results for future use. This can make your entire function lightning fast.
What’s really happening
Conceptually, storing data in a transient is like storing it in a variable, except that the storage is outside your code and is available in other scripts at other times. When you put your data into a transient WordPress intelligently stores it either in the database or an object cache. This is one of transients super powers. You don’t need to build the cache area, WordPress just takes care of it.
“But why?” you ask. “Why would we store the results of a database query in the database? How is that faster? The answer is that the first query is very complicated and takes a long time. Retrieving a transient from the database is a very simple query and is very fast.
Additionally, if you have an object cache for your site, transients will magically use it and those are super fast.
Transient lifetimes
As mentioned at the beginning of this post, transients aren’t supposed to live very long. When you create one you can tell it the maximum amount of time it can live, but it might not. It might not last more than a few seconds. Lots of things can delete transients, which means you cannot rely on them to always be there. It very common that you yourself write code to delete the transients.
“Why would I use them if they’re not reliable?” you ask. Because they’re mostly reliable, and that’s good enough. This simply means you need to code around the unreliability. When you want to use one you call it and test the contents. If they’re not there, you run your slow query and recreate the transient and move on.
This is an extremely common scenario when your source data changes often. Imagine you’re doing a fundraiser, and the total increments every few seconds, but you only want the website to update every 30 minutes. You would set a transient to live for 30 minutes, and then when it expired your code would run again, get a new total, and set a new transient.
Another common scenario is that you have some data in a meta field on a page or post. That gets stored in a transient, and you set the transient to live for a year. But what if the source data changes? You would also write some code to delete your transient when that post ID is saved. Then it can either be recreated when it’s called, or you could be preemptive and create a new transient right after deleting the old one.
Show me the code
<?php
/**
* This function returns a JSON blob that contains the URL of a photo of a dog.
*
* This function checks first for data in a transient and if it's not there, gets new data
* and recreates the transient. Then it always returns a JSON blob.
*
* @link https://dog.ceo/api/breeds/image/random
*
* @return strong JSON blob holding two vars, a message with a URL in it,
* and status with an http status in it
*/
function get_dailydog() {
// We're going to get a Daily Dog picture, so create an empty var for future use.
$dailydog = '';
// Next we make a name for our transient
$tname = 'dailydog';
// Next we try getting the data from the transient
$dailydog = get_transient( $tname );
// Now we test to see if we got data back. If we did not, go get it from the API
if ( empty( $dailydog ) ) {
// Go get the data.
$dog_request = wp_safe_remote_get( 'https://dog.ceo/api/breeds/image/random' );
// The data includes all the headers of the request, so let's get just the body.
$dog_data = wp_remote_retrieve_body( $dog_request );
// We're expecting JSON in the body, let's make sure we have that.
if ( json_validate( $dog_data ) ) {
// This will only run if we have valid JSON, so let's put this data
// into the transient.
// We want the transient to live for an hour, so for the time we'll
// use HOUR_IN_SECONDS.
set_transient( $tname, $dog_data, HOUR_IN_SECONDS );
// We'll ALSO load $dailydog with our data
$dailydog = $dog_data;
}
}
// At this point $dailydog will always have valid JSON with daily dog info in it.
return $dailydog;
}So now we have our data in a transient, and any time we want to get a photo of a dog we can simply call get_dailydog() and parse the JSON. Honestly you probably want to parse it in the above function and return just a URL, but I wanted to keep the function simple.
Clearing A Transient
Let’s say you want to clear a transient every time a post is saved. Here’s how you’d do that.
/**
* This function clears the $dailydog transient on Post save.
*
* @param integer $post_id The post_id of the post being saved.
*
* @return NULL
*/
function delete_dailydog_transient( $post_id ) {
// First we want to make sure that this is a real save, not simply an auto save
if ( ! wp_is_post_revision( $post_id ) ) {
// now we declare our custom content type, because we only want to run this
// on the save of this type
$post_type = 'post';
// this is where we actually make sure we're on the right type.
$_POST += array( $post_type . '_edit_nonce' => '' );
if ( $post_type != $_POST['post_type'] ) {
return;
}
// assuming we're on the proper type, set the transient name.
$tname = 'dailydog';
// now delete the actual transient.
delete_transient( $tname );
}
// end delete_dailydog_transient
}
// now we hook that function into save_post and it's all set
add_action( 'save_post', 'delete_dailydog_transient' );Warnings
Volatility
There is no guarantee that a transient is going to exist for any length of time at all. Lots of things can delete transients, like transient management plugins, site management tools, or optimization tools. For this reason, ALWAYS test the contents of your transient after running get_transient().
Name Length
Transient names are stored in the options table, and the name field is VARCHAR(255), so you might think you can have a name 255 characters long. HOWEVER, WordPress will prefix your name with “transient” or “transient_timeout” in the options table (depending on whether it expires or not). Longer key names will silently fail. For this reason never make your transient names longer than 172 characters.
This is NOT an issue if transients are stored in memcache.
Database Bloat
I mentioned that transients could be deleted by anything, but by the same token there is nothing in WordPress that deliberately deletes transients. They “expire” when their lifetime passes, but they’ll sit there in the database forever unless some action is taken to remove them. If you call set_transient() on a transient that exists but has expired, it will delete it and make a new one, rather than make a new one every time.
This is why it’s quite common for something like a site optimization plugin to simply delete them all. The needed ones will be recreated as soon as they’re needed, and the zombie transients will be flushed, this potentially making your database queries faster.
Again, none of this is an issue if you have memcache in place.
Summary
The above code allows us to get data from a public API, but not do that more than once per hour. Here again are some reasons why you’d want this.
- In the case of the Dogs API, it’s a free service, and beating on it every time a page loaded would be rude.
- In the case of an API where you pay for a certain number of queries, you can dramatically reduce costs by not re-fetching data that has already been fetched.
- Lastly, making an API call or making a complex query can be very slow, and make your entire page load more slowly. If there’s a problem with the connection between your site and the API it could even make your entire page time out and not load at all.
If you’re a developer, always be thinking about how long it takes your code to get data from anywhere, and when appropriate, simply store the results in a transient and enjoy the performance gains.
The post Put Your WordPress Code Into Hyper Drive With Transients appeared first on Performance Hub.




