Get an Expired Transient in WordPress: Good Idea or Crazy Talk?
I wonder if there’s an easy way to get an expired transient in WordPress? Now, for this to make sense I guess I should provide a little more context, so here it goes :)
The Transients API is an extremely easy way to cache parts of your WordPress code, that may be CPU/memory intensive, or rely on a third-party server and so on. A great example is grabbing a tweet from Twitter and caching it for a few minutes, so that we don’t query the Twitter API on every page load. So in theory:
if ( false === ( $tweet = get_transient( 'my_latest_tweet' ) ) ) {
$tweet = get_my_latest_tweet(); // Queries the Twitter API
set_transient( 'my_latest_tweet', $tweet, 60*60 );
}
Is a great way to cache my latest tweet for an hour. Perfect, but there’s a problem. The code above will work well for 60 minutes. When the transient expires, it will have to spend time again to fetch the tweet, thus impacting your page load time. Once every 60 minutes.
Suppose Twitter is being slow today and taking 2 seconds to respond back, and suppose I want to cache the tweet for 5 minutes, not an hour. This means that every 5 minutes, somebody will have to wait two extra seconds for my page to load. Suppose I’m querying the Flickr API, the Facebook API and fetching a few RSS feeds too, that will all add up to the page load time, to that unlucky person who visited my site, when the cache was expired. Bummer!
Is there a solution? I don’t know, but I can think of one — always serve cached data, even if it’s expired. That way visitors will never have to wait extra when you’re speaking to third party servers and APIs. I can think of a way to accomplish this by fetching the new data in a different request, transparent to the user.
Like an asynchronous request with jQuery (aka AJAX) to a special action that would revalidate expired cache. Crazy talk? Here’s the scenario:
- You visit your page when caches are empty, you don’t see the tweet.
- An async jQuery request is fired to the server which grabs the latest tweet and caches it, this happens behind your back.
- You refresh the page and you see the tweet from cache. Yey!
- Ten minutes have passed, cache is expired, but not trashed. You visit your page, you see the old tweet from (expired) cache.
- An async request in the back fetches a new tweet from Twitter and replaces the one expired.
- You refresh the page and you see the (new) tweet from cache. Yey!
So in steps 1, 3, 4 and 6 you’re always serving what’s in cache, whether it expired or not, even if it’s empty (first step) so you’re serving as fast as possible. Steps 2 and 5 happen behind your back, they don’t impact page load time, and they never return anything back. You won’t see them happening unless you’re looking at your Netwok tab in Chrome’s developer tools or Firebug.
Now, suppose Twitter is down. The visible steps are not impacted, because they return stored data, they don’t have to fetch it from Twitter. The hidden steps will fail, but your visitors will never know, since they’ll be still seeing the old tweet fetched some time earlier, right?
This can easily be done with the Options API but hey, transients are already a great tool for caching. Wouldn’t it be even easier if transients never actually expired? And a function to fetch such an expired transient, get_expired_transient perhaps? :)
Okay, that’s just off the top of my head, it’s quite late so, sorry if I’m totally on the wrong track. Let me know if there’s an easier solution, or maybe a caching plugin that already does this. Object caching can benefit too by the way. Share your thoughts in the comments section below!


