I first encountered the WordPress Transients API a couple of years back. I was reviewing the database tables on one of my blogs, and found that my wp_options table was full of hundreds of entries from the WordPress transients API. In my ignorance, I wanted to clean these out to optimize my database table, not realizing just how simple and useful the Transients API is.

According to the WordPress Codex, the WordPress Transients API “offers a simple and standardized way of storing cached data in the database temporarily by giving it a custom name and a time frame after which it will expire and be deleted.” In a standard WordPress installation, it stores this cached data in the wp_options table. If you have memcached enabled by your WordPress host, then this cache will persist in memory, rather than in the database.

The power of WordPress is that it is a dynamic, database-driven content management system. With that power comes performance problems, as each time you load a page, you run another database query, and most often the database hasn’t changed at all. Database queries take time and processing resources, and if you get hundreds or thousands of folks hitting your database at the same time, you are guaranteed to have performance issues because of all of the redundant database queries.

Using the Transients API

You want to use the Transients API whenever you have a computationally-intensive value that doesn’t change very often that you’d like to cache. In WordPress, this is usually going to be the resulting object from a database query, but it could really be anything you’d store in a variable, whether a scalar value, an array or an object. Let’s look at a simple example with a custom WP_Query object.

The following query will retrieve all of the posts in the database that have the category “Microsoft”.

$my_query = new WP_Query( 'category_name=microsoft' );

Since the list of posts only changes when we publish a new article, let’s wrap that query in the Transients API and store the result for an hour.

// Get any existing copy of our transient data
if ( false === ( $my_query = get_transient( 'my_query' ) ) ) {
    // It wasn't there, so regenerate the data and save the transient
     $my_query = new WP_Query( 'category_name=microsoft' );
     set_transient( 'my_query', $my_query, 1 * HOUR_IN_SECONDS );
}

// Use the data like you would have normally...

When you call set_transient, it saves the value of your variable, in this case $my_query, as a transient named my_query. It has an expiration time of 1 hour. Note that the expiration is the maximum, not absolute, amount of time that data will be cached. It can and will be deleted before the expiration time, especially when you are using Memcached as the in-memory object cache, but will never been returned after the expiration time is reached. After expiration, the query is run again to regenerate a fresh transient. Make sure that you recognize that a value stored in a transient is a cache, not a data store.

When in development, wait until you’re almost done to add your transient code. If you are trying to make the results of your query or function perfect, introducing caching of your results too soon will give you fits.

You also need to be aware that you need to give the transient a unique name that is 40 characters or less. We used to have a custom query that ran on every artcile page that was specific to that particular post. I needed to append the post ID to the end of each transient name to make each one unique.

Deleting a transient

If you are going to cache a list of posts from the database, your code has to deal with times when someone publishes or deletes a post. If you do nothing, your custom query is going to be out of date until it expires.

In our case, we hooked in to Post Status Transitions to deleted transients whenever a post was published or deleted. Depending on what you are trying to accomplish, you may need to watch for more events, such as post edits, etc.

function delete_transient($ID, $post) {
    delete_transient('my_query');
}
add_action('publish_post', 'delete_transient', 10, 2);
add_action('trash_post', 'delete_transient', 10, 2);

Using Query Monitor

If you are developing your own code, it is usually pretty obvious to find data results that deserve to be cached. However, if you are working with someone else’s code, theme or plugin, you need a tool to look for database query activity. We use Query Monitor all the time, a great plugin that will show you all of the database queries run for a particular page load, along with just how long it took to run each of those queries.

When you run Query Monitor, you will see all sorts of queries being run for things like WordPress options, users or taxonomy terms. Watch for WP_Query->get_posts, which are often the most expensive database queries. These are often great candidates to use the Transients API.

Latest Developer Blog Articles

Job Listings on GeekWork

Find more jobs on GeekWork. Employers, post a job here.