How to Use Transients in WordPress

Caching expensive queries and API responses with WordPress Transients

Transients are WordPress’s built-in caching layer. They store any serializable value in the database (or in an object cache like Redis/Memcached if one is installed) with an optional expiry time. They’re ideal for caching expensive queries, external API responses, or computed data.

Problem: How do you cache an expensive database query or external API response in WordPress so it runs only once per expiry period?

Solution: The three functions you need:

// Store a value for one hour
set_transient( 'my_transient_key', $data, HOUR_IN_SECONDS );

// Retrieve it (returns false if expired or not set)
$data = get_transient( 'my_transient_key' );

// Delete it manually
delete_transient( 'my_transient_key' );

A practical example — caching a slow database query:

function get_popular_posts() {
    $cache_key = 'popular_posts';
    $posts     = get_transient( $cache_key );

    if ( false !== $posts ) {
        return $posts;
    }

    $posts = new WP_Query( [
        'posts_per_page' => 10,
        'orderby'        => 'comment_count',
        'order'          => 'DESC',
        'no_found_rows'  => true,
    ] );

    set_transient( $cache_key, $posts, 12 * HOUR_IN_SECONDS );

    return $posts;
}

// Bust the cache when a post is updated
add_action( 'save_post', function() {
    delete_transient( 'popular_posts' );
} );

WordPress defines these handy time constants: MINUTE_IN_SECONDS, HOUR_IN_SECONDS, DAY_IN_SECONDS, WEEK_IN_SECONDS, MONTH_IN_SECONDS, YEAR_IN_SECONDS.

NOTE: Transients with no expiry (0) are persistent — they stay until deleted. If you use a persistent object cache, transients never touch the database at all, which is significantly faster. Always invalidate transients when the underlying data changes.