Are transients garbage collected?

This question got me thinking Transient RSS feeds in wp_options not removed automatically?

Transients are supposed to expire and be deleted. However the only way I see this handled is when transient is expired and requested, then it is deleted during request.

What if transient is expired but never requested after that? From description in Codex I thought that some kind of garbage collection is implied. Now I am not so sure and can’t find any code that performs such.

So will it just be stuck in database forever?


They now are

Starting with WordPress 3.7 expired transients are deleted on database upgrades, see #20316

Old answer

If someone can’t show me otherwise it seems that transients are not garbage collected after all. What makes it worse is that unlike options they are not guaranteed to be stored in database. So there is no reliable way to fetch list of all transients to check them for expiration.

Some makeshift code to do garbage collection if database is used for storage:

add_action( 'wp_scheduled_delete', 'delete_expired_db_transients' );

function delete_expired_db_transients() {

    global $wpdb, $_wp_using_ext_object_cache;

    if( $_wp_using_ext_object_cache )

    $time = isset ( $_SERVER['REQUEST_TIME'] ) ? (int)$_SERVER['REQUEST_TIME'] : time() ;
    $expired = $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout%' AND option_value < {$time};" );

    foreach( $expired as $transient ) {

        $key = str_replace('_transient_timeout_', '', $transient);

Leave a Comment