Rails Page Caching - OpenDemocracyManitoba/winnipegelection GitHub Wiki

Research by Rob Ring.

Overview

The WinnipegElection.ca website is static enough in content that it can be heavily cache. In this past this was done using page caching in our Rails controllers, like this:

caches_page :index, :mayor, :council

This one adds file-based caching for the index, mayor and council actions/views. Once a page was cached the Rails stack wouldn't be hit at all, the cached file would just be served directly from the project's /public folder. Unfortunately, Rails 4 no longer supports page caching, and while page caching is currently supported in a gem (actionpack-page_caching) support for is limited to Rails 4.1.

There are a number of other methods to cache with Rails. However, most of these are memory based and any that are optimised for performance require running another layer between your server and client.

Rack::Cache is built into Rails and offers caching through a file-store. Combined with conditional GET support, this approach is the simplest approach to file-based caching, but is not optimised for performance. Based on the requirements, Rack:Cache using conditional GET support is suggested for the ODM sites.

Alternatives

It’s worth noting some of the alternatives for caching, if in the future it’s decided that caching needs to be optimised for performance.

  1. Memcached - memory-based caching system that is highly optimised
  2. Varnish - http cache that works similarly to conditional GET support in Rails:Cache but is optimised for performance

Rack::Cache

There are three primary ways to cache using conditional GET support with Rack::Cache.

# expires_in
expires_in 60.minutes, public: true

# stale?
if stale? (@cache)
  respond_to do |format|
    format.html
  end
end

# fresh_when
fresh_when(@cache, public: true) 

Of these three, fresh_when is the simplest to use, provided there is no special response processing and the default view is being rendered. stale? and fresh_when behave similarly and will trigger a 200 status code when content is updated based on last_modified and etag.

Cache Store

AcitveSupport::Cache::FileStore is the default cache store implementation with Rails 4 The cache store is appropriate for low to medium traffic sites that are served off one or two hosts. Note that the cache will grow until the disk is full unless you periodically clear out old entries.

HTTP Headers - Cache Styles

A spreadsheet of sample HTTP Header outputs for the three Conditional GET approaches described above.

Resources