Wordpress: Cache RSS Feeds to Lower CPU Usage – December 09, 2009

I did some work for a client who was having high CPU load issues with their tiny (20 posts, no comments) Wordpress installation.

They already had the super-cache plugin installed (I think that should be shipped by default in wordpress), but the super-cache plugin (as of version 0.9.6.1) doesn't cache RSS feeds, so for each of the ~5000 viewers of the RSS feed, the feed is regenerated each time, causing this tiny site to be the largest CPU usage of all sites on this particular shared server.

It turns out that this is a known problem, so hopefully it will be fixed in later releases of the plugin. Especially since I am asked to fix this for different clients at different times, and I have to relearn how to fix it each time, because I can't keep it in my head...

The changes I made were:

modified wp-cache-phase2.php, line 36:

if ( $wp_cache_not_logged_in && is_user_logged_in() /*&& !is_feed()*/ && !is_admin() ) {

modified wp-cache-phase2.php, line 270:

if( !empty( $_GET ) || /*is_feed() ||*/ ( $super_cache_enabled == true && is_dir( substr( $supercachedir, 0, -1 ) . '.disabled' ) ) )

added to wp-cache-phase2.php, on line 364:

if (is_feed()) {
  $type = get_query_var('feed');
  $type = str_replace('/','',$type);
  switch ($type) {
    case 'atom':
      $mediaType = "application/atom+xml";
      break;
    case 'rdf':
      $mediaType = "application/rdf+xml";
      break;
    case 'rss':
    case 'rss2':
    default:
      $mediaType = "application/rss+xml";
  }
  $htaccess = @fopen ("{$dir}.htaccess", 'w');
  if ($htaccess) {
    fputs($htaccess, "<Files *.html>\n ForceType $mediaType\n</Files>\n");
    fputs($htaccess, "<Files *.gz>\n ForceType $mediaType\n</Files>\n");
    fclose($htaccess);
  }
}

added to .htaccess,top of file

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/$
RewriteCond %{QUERY_STRING} ^feed=rss2?$
RewriteRule ^.*  /feed/?   [R,L]
RewriteRule ^feed$  /feed/   [R,L]

The code now traps /?feed=rss, /?feed=rss2, /feed and redirects them to /feed/ which is now cached appropriately by super-cache.

The changes/additions I made to Michael's fixes:

  1. compressed feeds (.gz extension) work
  2. the client's server required ForceType rather than AddType
  3. I also wanted the "extra" feed URLs captured, so apache would handle the static files, rather than forcing Wordpress to dynamically redirect them

Questions? Have Anything to Add?
(your comments will be published on this site - click here for private questions)

I upgraded supercache this morning (to version 0.9.8) and it still doesn't properly cache feeds, so I re-applied the updates, the only change is the line numbers - the first two are easy enough to find, just search for is_feed() and the last one I added on line 374, just after the cache directory is created.

Posted by Jon Daley on December 10, 2009, 11:06 am

So helpful. I was suffering from this same problem today and I'm happy to have found this fix!

Posted by Matt on January 9, 2010, 8:44 pm