Title: An introduction to the Transients API
Author: Ryan Welcher
Published: June 11, 2024
Last modified: June 12, 2024

---

 * [Showcase](https://wordpress.org/showcase/)
 * [Plugins](https://wordpress.org/plugins/)
 * [Themes](https://wordpress.org/themes/)
 * [Hosting](https://wordpress.org/hosting/)
 * [News](https://wordpress.org/news/)
    - [Learn WordPress](https://learn.wordpress.org/)
    - [Documentation](https://wordpress.org/documentation/)
    - [Education](https://wordpress.org/education/)
    - [Forums](https://wordpress.org/support/forums/)
    - [Developers](https://developer.wordpress.org/)
    - [Blocks](https://wordpress.org/blocks/)
    - [Patterns](https://wordpress.org/patterns/)
    - [Photos](https://wordpress.org/photos/)
    - [Openverse ︎](https://openverse.org/)
    - [WordPress.tv ︎](https://wordpress.tv/)
 *  - [About WordPress](https://wordpress.org/about/)
    - [Make WordPress](https://make.wordpress.org/)
    - [Events](https://events.wordpress.org/)
    - [Five for the Future](https://wordpress.org/five-for-the-future/)
    - [Enterprise](https://wordpress.org/enterprise/)
    - [Gutenberg ︎](https://wordpress.org/gutenberg/)
    - [Job Board ︎](https://jobs.wordpress.net/)
 * [Swag ︎](https://mercantile.wordpress.org/)
 * [Get WordPress](https://wordpress.org/download/)

Search in WordPress.org

 [ Get WordPress ](https://wordpress.org/download/)

[WordPress Developer Blog](https://developer.wordpress.org/news)

An introduction to the Transients API

 * [Snippets](https://developer.wordpress.org/news/snippets/)
    - [Blocks](https://developer.wordpress.org/news/category/blocks/)
    - [Concepts](https://developer.wordpress.org/news/category/concepts/)
    - [Common APIs](https://developer.wordpress.org/news/category/common-apis/)
    - [Design](https://developer.wordpress.org/news/category/design/)
    - [Playground](https://developer.wordpress.org/news/category/playground/)
    - [Plugins](https://developer.wordpress.org/news/category/plugins/)
    - [Themes](https://developer.wordpress.org/news/category/themes/)
 *  - [About this site](https://developer.wordpress.org/news/about/)
    - [Updates](https://developer.wordpress.org/news/category/updates/)
    - [How to contribute](https://developer.wordpress.org/news/how-to-contribute/)
    - [Tips and guidelines](https://developer.wordpress.org/news/tips-and-guidelines-for-writers/)
 * [Subscribe](https://developer.wordpress.org/news/subscribe/)
 * [Developer Resources](https://developer.wordpress.org/)

 * [Snippets](https://developer.wordpress.org/news/snippets/)
    - [Blocks](https://developer.wordpress.org/news/category/blocks/)
    - [Concepts](https://developer.wordpress.org/news/category/concepts/)
    - [Common APIs](https://developer.wordpress.org/news/category/common-apis/)
    - [Design](https://developer.wordpress.org/news/category/design/)
    - [Playground](https://developer.wordpress.org/news/category/playground/)
    - [Plugins](https://developer.wordpress.org/news/category/plugins/)
    - [Themes](https://developer.wordpress.org/news/category/themes/)
 *  - [About this site](https://developer.wordpress.org/news/about/)
    - [Updates](https://developer.wordpress.org/news/category/updates/)
    - [How to contribute](https://developer.wordpress.org/news/how-to-contribute/)
    - [Tips and guidelines](https://developer.wordpress.org/news/tips-and-guidelines-for-writers/)
 * [Subscribe](https://developer.wordpress.org/news/subscribe/)
 * [Developer Resources](https://developer.wordpress.org/)

# An introduction to the Transients API

By [Ryan Welcher](https://profiles.wordpress.org/welcher/)

June 11, 2024

[Beginners](https://developer.wordpress.org/news/category/beginners/), [Common APIs](https://developer.wordpress.org/news/category/common-apis/),
[Plugins](https://developer.wordpress.org/news/category/plugins/)

Everyone wants a fast website. The faster the site, the longer a user stays and 
clicks on pages or buys products. One of ways to speed up your site is to implement
caching. The idea behind caching is to store information so that it’s accessed faster
than connecting to the database would be. To use an analogy, it’s much faster to
go to your fridge to get a snack than it would be to drive to the store, find it
on the shelf, pay for it, and then drive home to eat it.

There are a number of types of caching; object caching, browser caching, page caching
and even database caching. Each type has its purpose and setup steps that can range
from [installing a plugin](https://en-ca.wordpress.org/plugins/search/Caching/) 
to changing your server configuration to enable object caching. In this article,
you will learn about the Transients API, which can be either object or database 
caching – depending on where it’s being used.

The [Transients API](https://developer.wordpress.org/apis/transients/) is used to
temporarily store information in WordPress across page loads. In a default installation,
this information is stored in the options table of the database. This is very similar
to the [Options API](https://developer.wordpress.org/plugins/settings/options-api/)
but with the ability to set an expiration time after which the data will be deleted.

Transients are a very powerful tool that can be used to not only avoid needless 
database requests for page content but also speed up generating complicated markup
and mitigate slow third-party API requests. 

Table of Contents

 1.  [Saving a transient](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#saving-a-transient)
 2.  [Retrieving a transient](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#retrieving-a-transient)
 3.  [Removing a transient](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#removing-a-transient)
 4.  [Object caching](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#object-caching)
 5.  [Transient expiration](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#transient-expiration)
 6.  [Always set an expiration time](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#always-set-an-expiration-time)
 7.  [When should you use transients?](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#when-should-you-use-transients)
 8.  [Code examples](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#code-examples)
 9.   a. [Retrieving or regenerating transient data](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#retrieving-or-regenerating-transient-data)
      b. [Priming the cache](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#priming-the-cache)
      c. [Storing markup](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#storing-markup)
      d. [Storing API responses](https://developer.wordpress.org/news/2024/06/11/an-introduction-to-the-transients-api/#storing-api-responses)

## Saving a transient

To save a transient, you can use the `[set_transient](https://developer.wordpress.org/reference/functions/set_transient/)`
function. It accepts three parameters: the name of the transient, the data to be
stored, and an optional expiration time in seconds. And it will return `true` if
the transient was set.

The snippet below sets a transient with an expiration of one week.

    ```php
    set_transient( 'dev-blog-transient', 'Some data I want to persist', WEEK_IN_SECONDS );
    ```

There are a number of [constants available in WordPress to calculate time](https://developer.wordpress.org/apis/transients/#saving-transients)
that are very helpful when working with the Transients API and make your code much
more readable. `WEEK_IN_SECONDS` is much easier to understand than `604800`.

## Retrieving a transient

To retrieve the data stored in a transient, you can use [`get_transient`](https://developer.wordpress.org/reference/functions/get_transient/).
This function accepts a single parameter—the name of the transient to retrieve—and
returns the data or `false` if the transient does not exist or has expired.

    ```php
    $persisted_data = get_transient( 'dev-blog-transient' );
    ```

It’s always best to check for the data using the `===` operator to confirm that 
both data exists and are of the same type. There may be cases where the transient
data is “falsey,” such as the number zero or the string “false,” but makes sense
for what the data is being used for. Using strict comparison protects you against
a false negative in that case.

The snippet below demonstrates a common approach to check for the transient data
and sets you up to be able to regenerate the transient.

    ```php
    if ( false === ( $persisted_data = get_transient( 'dev-blog-transient' ) ) ) {
      // This will run if there is no transient or it has expired.
    } 
    ```

## Removing a transient

Any transient can be deleted at any time using the [`delete_transient`](https://developer.wordpress.org/reference/functions/delete_transient/)
function. This function also accepts a single parameter of the transient name and
will return `true` if the transient was deleted.

    ```php
    delete_transient( 'dev-blog-transient' );
    ```

## Object caching

Before you can fully understand the Transients API, you need to know how WordPress’
in-memory or object caching system works. Object caching allows you to store items
that might be computationally expensive for later use in memory.

A great use-case for this is when you have an expensive WP_Query whose results are
needed more than once. Caching the results allows you to avoid multiple trips to
the database to retrieve the data and speeds up your processing time.

WordPress uses the `WP_Object_Class` behind the scenes to power this cache, but 
you would use the `wp_cache_* `family of [functions](https://developer.wordpress.org/reference/classes/wp_object_cache/#wp_cache_-functions)
to interact with it.

The default object cache is not persistent, meaning that anything that has been 
cached will disappear once the page is finished loading. It is possible to change
the object cache to be persistent using a number of [caching plugins](https://developer.wordpress.org/reference/classes/wp_object_cache/#persistent-cache-plugins).
Setting this up is beyond the scope of this article but it usually requires modifications
on the server and adding the `object-cache.php` drop-in to override the default 
object cache.

By this point, you’re probably wondering what this has to do with the Transients
API. Well, once there is a persistent cache in-place, the Transients API will no
longer store its data in the database via the Options API and will instead use `
WP_Object_Class` to persist its data. The immediate benefit here is speed. Accessing
data stored in memory can be much faster than querying the database for that same
data.

The best part is that you don’t have to make any changes to your code to gain the
performance benefits. The changes are all handled under the hood.

## Transient expiration

The concept of transient expiration time is commonly misunderstood. Ryan McCue has
an excellent quote in the [official documentation that explains it nicely](https://developer.wordpress.org/apis/transients/#overview):

> Everyone seems to misunderstand how transient expiration works, so the long and
> short of it is: transient expiration times are a maximum time. There is no minimum
> age. Transients might disappear one second after you set them, or 24 hours, but
> they will never be around after the expiration time.
>  Ryan McCue

This is the case due to a number of external factors such as database updates or
the object cached being purged. As such, you should always assume that the transient
doesn’t exist and write your code accordingly.

This also means that even if you set your transient to have an expiration time of
100 years from now, there is no guarantee that the data will persist until then.

## Always set an expiration time

When setting a transient, you can leave out the expiration time parameter and have
it default to `0` seconds.

    ```php
    set_transient( 'dev-blog-transient', 'Some data I want to persist' ); 
    ```

This effectively tells the API that this data should not be available after 0 seconds.
While this may seem like a good approach for data that’s not needed for very long,
it has a potentially nasty side effect that only pertains to when transients are
being saved to the database.

As you now know, under the hood, transients are saved to the database via the Options
API. But if you take a [closer look at the source code](https://github.com/WordPress/wordpress-develop/blob/6.5/src/wp-includes/option.php#L1311),
you will see that any transients without an expiration time will have the corresponding
option set to autoload.

    ```php
    $autoload = 'yes';
    if ( $expiration ) {
        $autoload = 'no';
        add_option( $transient_timeout, time() + $expiration, '', 'no' );
    }
    $result = add_option( $transient_option, $value, '', $autoload );
    ```

This means that this data will be automatically loaded for every page request, even
if it’s never used. Imagine 1000 transients with large datasets being retrieved 
on every page load—this has a potentially huge impact on your site performance. 

The easiest way to avoid this issue (besides having an object cache in place) is
to always set an expiration time, even if it’s only for one second.

    ```php
    set_transient( 'dev-blog-transient', 'Persisted but not autoloaded data', 1 ); 
    ```

If you’re not using an object cache and want to persist data during the page load
but don’t need a transient, use [wp_cache_set()](https://developer.wordpress.org/reference/functions/wp_cache_set/)
and [wp_cache_get()](https://developer.wordpress.org/reference/functions/wp_cache_get/)
to set and retrieve data that will disappear after the page is finished loading.

## When should you use transients?

This will depend on where your code is being run and if you know the environment.

In some cases you will know where your code is going to be run. Whether it’s a client
site or your own. The server configuration is known to you and it’s possible to 
determine if there is a persistent object cache like [Redis](https://redis.io/) 
or [Memcached](https://memcached.org/) in place. In this case, you can use the Transients
API or the` wp_cache_*` functions as transients are being stored in the object cache
as explained above.

If you’re releasing that plugin or theme publicly, there is no way to know what 
kind of server environment your code will be running in. In this case, it’s better
to use the Transients API as it is guaranteed to save to the database.

**TL;DR: **If you need to ensure that data will be persisted in any server environment,
then use the Transient API.

## Code examples

### Retrieving or regenerating transient data

Probably the most common example is when you want to check for a transient and generate
it if it doesn’t exist.

In this example, you are retrieving a list of post IDs. In the case that the transient
returns `false`, you generate the query and then use `set_transient` to store only
the array of IDs returned from the query. The important part here is that the same
variable name, `$persisted_data`,  is used for both retrieving the transient and
the final generated list of IDs. This ensures the rest of your code will work regardless
of whether the transient exists or not.

    ```php
    if ( false === ( $persisted_data = get_transient( 'dev-blog-post-id-list' ) ) ) {
        // The transient doesn't exist or has expired so you need to regenerate
        $query = new WP_Query( array( 'posts_per_page' => 25, 'fields' => 'ids' ) );
        if ( $query->have_posts() ) {
            $persisted_data = $query->posts;
        } else {
            $persisted_data = array();
        }
        set_transient( 'dev-blog-post-id-list', $persisted_data, WEEK_IN_SECONDS );
    }
    ```

### Priming the cache

A really great technique that can help with ensuring that your site visitors have
a performant experience is to “prime” your caches. This essentially means that when
a change is made on your site, you can regenerate any related transients so that
when a user visits your site, they are ready to be retrieved.

In this snippet, you are going to prime a transient when a post is saved.

    ```php
    add_action(
        'save_post',
        function () {
            // The post was saved.
            $query = new WP_Query( array( 'posts_per_page' => 25, 'fields' => 'ids' ) );
            if ( $query->have_posts() ) {
                $persisted_data = $query->posts;
            } else {
                $persisted_data = array();
            }
            set_transient( 'dev-blog-post-id-list', $persisted_data, WEEK_IN_SECONDS );
        },
    );
    ```

### Storing markup

Transients don’t always have to store data. In some cases, it may be more performant
to generate and store some markup. The concepts are the same, check for the transient
and then regenerate the markup and save it if it doesn’t exist.

Here you are going to retrieve the five most recent posts and generate a list showing
the post title and author name.

    ```php
    if ( false === ( $markup = get_transient( 'stored_markup' ) ) ) {
        $query  = new WP_Query( array( 'posts_per_page' => 5 ) );
        $markup = '';
        if ( $query->have_posts() ) {
            $markup .= '<ul>';
            foreach ( $query->posts as $post ) {
                $markup .= '<li>';
                $markup .= get_the_title( $post->ID ) . ' | ';
                $markup .= get_the_author_meta( 'nicename', $post->post_author );
                $markup .= '</li>';
    	}
    	$markup .= '</ul>';
    	set_transient( 'stored_markup', $markup, WEEK_IN_SECONDS );
        }
    }
    ```

### Storing API responses

The responses from third-party API requests are a fantastic candidate for transients.
It’s pretty rare that you would want to have every page load make a new request 
and in fact storing the results in a transient will mitigate any issues with rate-
limiting or slow responses from the API.

In this snippet, you’re going to make a request to a third-party meme generator 
service and store the meme data in a transient.

    ```php
    if ( false === ( $api_data = get_transient( 'stored_memes' ) ) ) {

    	// Make the request to the API.
    	$response = wp_remote_get( 'https://api.imgflip.com/get_memes', array( 'headers' => array( 'Content-Type'  => 'application/json') ) );

    	// Ensure that there is a response.
    	if ( ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response ) ) {

    		// Retrieve the body of the request.
    		$body = wp_remote_retrieve_body( $response );

    		// Process API data.
    		$api_data_json = json_decode( $body, true );
    		$api_data      = $api_data_json['data']['memes'];

    		// Store the results for a maximum of 1 hour.
    		set_transient( 'stored_memes', $api_data, MINUTE_IN_SECONDS * 60 );
    	}
    }
    ```

Have you used transients in an interesting or unexpected way? If so, share your 
examples in the comments!

_Props [@greenshady](https://profiles.wordpress.org/greenshady/) and [@milana\_cap](https://profiles.wordpress.org/milana_cap/)
for review of this article._

**Share the post: **

**Categories:** [Beginners](https://developer.wordpress.org/news/category/beginners/),
[Common APIs](https://developer.wordpress.org/news/category/common-apis/), [Plugins](https://developer.wordpress.org/news/category/plugins/)

**Tags:** [Caching](https://developer.wordpress.org/news/tag/caching/), [Extenders](https://developer.wordpress.org/news/tag/extenders/),
[Transients API](https://developer.wordpress.org/news/tag/transients-api/)

## 3 responses to “An introduction to the Transients API”

 1.  ![Michael Avatar](https://secure.gravatar.com/avatar/196493a0bf75ac95c77f6116f8cd683f9bb71346131f11844b5c10c27b176779?
     s=40&d=identicon&r=g)
 2.  [Michael](https://www.scoredetect.com/)
 3.  [June 11, 2024](https://developer.wordpress.org/news/2024/06/an-introduction-to-the-transients-api/#comment-6730)
 4.  Thanks for the guide!
 5.  I found that the code examples may not be suitable for production. For example,
     setting the “variable” inside the “if” statement. Could this be updated so that
     it shows WP coding standards and best practices?
 6.  Kind regards,
      Michael
 7.  [Reply](https://developer.wordpress.org/news/2024/06/an-introduction-to-the-transients-api/?replytocom=6730#respond)
 8.   a. ![Ryan Welcher Avatar](https://secure.gravatar.com/avatar/865d90ad698b325440361a71943d729f8ad5c44c66a6d65c5a046a8323ac7ced?
         s=40&d=identicon&r=g)
      b. [Ryan Welcher](https://profiles.wordpress.org/welcher/)
      c. [June 11, 2024](https://developer.wordpress.org/news/2024/06/an-introduction-to-the-transients-api/#comment-6731)
      d. Hi Michael and thank you for sharing your concern!
      e. The examples are meant to demonstrate the concepts and sometimes brevity is needed
         to keep them simple.
      f. That being said, these examples will run without issue in a production environment
         and match the existing documentation for transients (see [https://developer.wordpress.org/apis/transients/#fetching-transients](https://developer.wordpress.org/apis/transients/#fetching-transients)
         for an example).
      g. I personally have used this approach on many high-traffic sites but I would encourage
         anyone using any examples from the Developer Blog article to test them prior 
         to deploying them on a site.
      h. [Reply](https://developer.wordpress.org/news/2024/06/an-introduction-to-the-transients-api/?replytocom=6731#respond)
 9.  ![Grant M. Kinney Avatar](https://secure.gravatar.com/avatar/9207f792535aea5e539e41783596bd82fff6e0fccd3a0badc372e8ba1f7ba657?
     s=40&d=identicon&r=g)
 10. [Grant M. Kinney](https://profiles.wordpress.org/grantmkin/)
 11. [June 11, 2024](https://developer.wordpress.org/news/2024/06/an-introduction-to-the-transients-api/#comment-6736)
 12. Another good thing to know about transients is how they work in a multisite environment.
 13. In multisite, `get_transient` and `set_transient` have their cache keys prefixed
     automatically so that each cache entry is unique to the current site. For example,
     if you use `set_transient( ‘dev-blog-transient’, …` on 2 different sites in the
     network, you’ll end up with 2 separate cache items, even if those items store 
     the exact same data.
 14. If the data you’re caching is not unique to each site, you can use `get_site_transient`
     and `set_site_transient`. These are shared across the network, only create one
     cache item per transient, and will return the same cached data for all sites.
 15. [Reply](https://developer.wordpress.org/news/2024/06/an-introduction-to-the-transients-api/?replytocom=6736#respond)

### Leave a Reply 󠀁[Cancel reply](https://developer.wordpress.org/news/2024/06/an-introduction-to-the-transients-api/?output_format=md#respond)󠁿

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

Comment *

Name *

Email *

Website

 Save my name, email, and website in this browser for the next time I comment.

 Notify me of follow-up comments by email.

 Notify me of new posts by email.

Δ

## Have an idea for a new post?

### 󠀁[Learn how to contribute](https://developer.wordpress.org/news/how-to-contribute/)󠁿

Share your knowledge with fellow WordPress developers.

Search

### 󠀁[Review tips and guidelines](https://developer.wordpress.org/news/tips-and-guidelines-for-writers/)󠁿

Everything you need to know about writing for the Blog.

## Subscribe to the Blog

  Email Address

 Join 1,771 other subscribers

 * [About](https://wordpress.org/about/)
 * [News](https://wordpress.org/news/)
 * [Hosting](https://wordpress.org/hosting/)
 * [Privacy](https://wordpress.org/about/privacy/)

 * [Showcase](https://wordpress.org/showcase/)
 * [Themes](https://wordpress.org/themes/)
 * [Plugins](https://wordpress.org/plugins/)
 * [Patterns](https://wordpress.org/patterns/)

 * [Learn](https://learn.wordpress.org/)
 * [Documentation](https://wordpress.org/documentation/)
 * [Developers](https://developer.wordpress.org/)
 * [WordPress.tv ](https://wordpress.tv/)

 * [Get Involved](https://make.wordpress.org/)
 * [Events](https://events.wordpress.org/)
 * [Donate ](https://wordpressfoundation.org/donate/)
 * [Swag ](https://mercantile.wordpress.org/)

 * [WordPress.com ](https://wordpress.com/?ref=wporg-footer)
 * [Matt ](https://ma.tt/)
 * [bbPress ](https://bbpress.org/)
 * [BuddyPress ](https://buddypress.org/)

 * [Visit our X (formerly Twitter) account](https://www.x.com/WordPress)
 * [Visit our Bluesky account](https://bsky.app/profile/wordpress.org)
 * [Visit our Mastodon account](https://mastodon.world/@WordPress)
 * [Visit our Threads account](https://www.threads.net/@wordpress)
 * [Visit our Facebook page](https://www.facebook.com/WordPress/)
 * [Visit our Instagram account](https://www.instagram.com/wordpress/)
 * [Visit our LinkedIn account](https://www.linkedin.com/company/wordpress)
 * [Visit our TikTok account](https://www.tiktok.com/@wordpress)
 * [Visit our YouTube channel](https://www.youtube.com/wordpress)
 * [Visit our Tumblr account](https://wordpress.tumblr.com/)

![Code is Poetry](https://s.w.org/style/images/code-is-poetry-for-dark-bg.svg)

 The WordPress® trademark is the intellectual property of the WordPress Foundation.