Cedar does not include a reverse proxy cache such as Varnish, preferring to empower developers to choose the CDN or caching solution that best serves their needs. You can use Rack::Cache your Rails application to improve response time and decrease load. This is important if you're using the asset pipeline and serving static assets through your application.
Sample code for this article's [reference application](https://github.com/heroku/rack-cache-demo) is available on GitHub and can be seen running at [http://rack-cache-demo.herokuapp.com/](http://rack-cache-demo.herokuapp.com/)
Rack::Cache is rack middleware that enables HTTP caching on your application and can allow us to serve assets from a storage backend without requiring work from your main Rails application. Many Ruby web frameworks including Rails 3+ and Sinatra, are built on top of Rack. At a high level, Rack works by taking a request and passing it through a series of steps, called middleware. Each Rack middleware performs some action, then passes the request to the next middleware in the rack. Eventually the request is properly formatted and it will reach your application.
Rack is written to be lightweight and flexible. If middleware can respond to a request directly, then it doesn't have to hit your Rails application. This means that the request is retuned faster, and the overall load on the Rails application is decreased.
Rack::Cache has two different storage areas, meta and entity store, which can be configured for use with three different storage backends ,file, heap, and memcache. The metastore in Rack::Cache keeps high level information about each cache entry including headers. The entitystore is the response body content, the actual object being returned through the server. Storing data in a file is slow but memory efficient; using heap means your process' memory will be used which is quicker, but can have serious impacts; and using memcache is the fastest option, but isn't well suited to store large objects.
Since the metastore is accessed frequently and is much smaller than the entitystore, you can use memcache for the backend, but to keep the amount of data stored in Memcache to a minimum, you can write the entitystore to a temporary file. Heap storage is not recommended. For more information on the entity and meta stores read more about Rack Cache Storage.
Configuring your application to use [Memcache](http://devcenter.heroku.com/articles/memcache)
Since you will use memcache in your Rack::Cache metastore, you will first need to add it to your project. Heroku recommends using Memcache with the Dalli gem as part of your Rack::Cache backend.
You'll need to configure your Heroku application to use Memcache.
:::term
$ heroku addons:add memcache
To get this running on your local machine you will need to have Memcache installed. You can install it using a tool such as homebrew.
:::term
$ brew install memcache
At the end of installation homebrew will give you instructions on how to start Memcache manually and automatically on system start.
You can then tell your application to use Dalli, Heroku's preferred Memcache client. In your Gemfile add
:::term
gem 'dalli'
Then in your config/application.rb add
:::term
config.cache_store = :dalli_store
If you start a Rails console session you should now have access to Memcache
:::term
> memcache = Dalli::Client.new
> memcache.set('foo', 'bar')
> memcache.get('foo') # => 'bar'
Once you have configured your application to use memcached, you can configure Rack::Cache for use in your application.
For Rails 3.1+ you will need to modify your config/production.rb to tell rack_cache to use Memcache. By default Dalli::Client.new will look for the proper environment variables (ENV["MEMCACHE_SERVERS"]) when deployed to Heroku, and otherwise will default to localhost and the default port. If you want, rather than specifying an object, you can pass the connection string needed to talk to an external memcache server.
:::term
# This will tell `Rack::Cache` to use the default settings of Dalli, Heroku's recommended Memcache Gem
config.action_dispatch.rack_cache = {
:metastore => Dalli::Client.new,
:entitystore => 'file:tmp/cache/rack/body',
:allow_reload => false }
You can set the entitystore to write to a temporary file in the rails directory.
To allow your application to serve static files from /public you need to set config.servestatic_assets to true.
:::term
# This will allow Action::Dispatch to serve files from /public when set to true
config.serve_static_assets = true
Finally you need to tell the cache how long an item should stay in cache by setting the Cache-Control headers. Without a Cache-Control header, static files will not be stored by Rack::Cache
:::term
# This will set Cache-Control headers used by browsers
config.static_cache_control = "public, max-age=2592000"
Since these settings will tell Rack::Cache to store static elements for a very long time, it is important that you let your cache store know when you change a file. Typically cache invalidation can be very tricky, so to avoid that problem you can ensure that Rails generates a new file name every time you modify a file. This is done by using a hash digest such as MD5 on your files, tell Rails to do this automatically by setting config.assets.digest to true.
:::term
# Generate digests for assets URLs
config.assets.digest = true
You also want to ensure that caching is turned on.
# Enables caching including `Rack::Cache`
config.action_controller.perform_caching = true
Once all of this is set up correctly, you should see cache lines in your production log. The 'miss, store' indicates that the item was not found in the cache but has been saved for the next request
:::term
cache: [GET /assets/application-95bd4fe1de99c1cd91ec8e6f348a44bd.css] miss, store
cache: [GET /assets/application-95fca227f3857c8ac9e7ba4ffed80386.js] miss, store
cache: [GET /assets/rails-782b548cc1ba7f898cdad2d9eb8420d2.png] miss, store
The 'fresh' indicates item was found in cache and will be served from cache
:::term
cache: [GET /assets/application-95bd4fe1de99c1cd91ec8e6f348a44bd.css] fresh
cache: [GET /assets/application-95fca227f3857c8ac9e7ba4ffed80386.js] fresh
cache: [GET /assets/rails-782b548cc1ba7f898cdad2d9eb8420d2.png] fresh
If a setting is not configured properly, you might see miss in your logs instead of store or fresh as seen below. Make sure that you're using a hard refresh to clear your browser cache while you're investigating the problem.
:::term
cache: [GET /assets/application-95bd4fe1de99c1cd91ec8e6f348a44bd.css] miss
cache: [GET /assets/application-95fca227f3857c8ac9e7ba4ffed80386.js] miss
cache: [GET /assets/rails-782b548cc1ba7f898cdad2d9eb8420d2.png] miss
When this happens, ensure that the Cache-Control header exists. It can be easier to debug locally so you need to set up your project to be run in production locally.
:::term
$ bundle exec rake db:create RAILS_ENV=production
Compile assets with
:::term
$ bundle exec rake assets:precompile RAILS_ENV=production`
You can then start your application locally in production
:::term
$ bundle exec rails s -e production
Next copy one of your asset urls and curl it in the terminal using -I which will return the headers. It for an asset like rails.png it would look similar to this.
:::term
$ curl 'http://localhost:3000/assets/rails-782b548cc1ba7f898cdad2d9eb8420d2.png' -I
The result should look something like below, where Cache-Control returns public, max-age=2592000
:::term
$ curl 'http://localhost:3000/assets/rails-782b548cc1ba7f898cdad2d9eb8420d2.png' -I
HTTP/1.1 200 OK
Last-Modified: Sun, 18 Mar 2012 00:19:19 GMT
Content-Type: image/png
Cache-Control: public, max-age=2592000
Content-Length: 6646
Date: Sun, 18 Mar 2012 21:27:07 GMT
X-Content-Digest: 501d6b0108b930264e19f37cb8ee6c8222d4f30d
Age: 689
X-Rack-Cache: fresh
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Connection: Keep-Alive
You can also ensure that you are seeing and X-Rack-Cache header indicating the status of your asset (fresh/store/miss).
If you choose to use file storage for your entity store as demonstrated above, you can try deleting contents of the cache on disk, if your store is set to write to file:tmp/cache/rack/body you would go to your Rails root and remove all entries under tmp/cache/rack/body. When debugging using this step, do not forget to do a hard refresh in the browser.
If you modify a file and your server continues to serve the old file, check that you committed the file to your Git repository before deploying, and you can check to see if it exists in your compiled code by using heroku run bash
:::term
$ heroku run bash
Running bash attached to terminal... up, run.1
~ $ ls public/assets
application-95bd4fe1de99c1cd91ec8e6f348a44bd.css application.css manifest.yml
application-95bd4fe1de99c1cd91ec8e6f348a44bd.css.gz application.css.gz rails-782b548cc1ba7f898cdad2d9eb8420d2.png
application-95fca227f3857c8ac9e7ba4ffed80386.js application.js rails.png
application-95fca227f3857c8ac9e7ba4ffed80386.js.gz application.js.gz
Don't forget to check if the file exists in your manifest.yml
:::term
~ $ cat public/assets/manifest.yml
rails.png: rails-782b548cc1ba7f898cdad2d9eb8420d2.png
application.js: application-95fca227f3857c8ac9e7ba4ffed80386.js
application.css: application-95bd4fe1de99c1cd91ec8e6f348a44bd.css
If the file you're looking for does not show up try running bundle exec rake assets:precompile RAILS_ENV=production locally and ensure that it is in your own public/assets directory.

Great stuff. Few comments:
heroku addons:add memcachepart of the process inline here instead of linking out to http://devcenter.heroku.com/articles/memcache#using_memcache_from_ruby. The pattern here is to include the link for more background on Memcached in a callout: http://devcenter.heroku.com/articles/writing#calloutsMEMCACHE_SERVERSin a.envetc...). Minus installing memcached locally, I think we should cover it. Many of our tutorials have the pattern of describing code, running locally and deploying - we should try and mimic.MEMCACHE_SERVERSenv var? If not - how can you just sayDalli::Client.newin the rack-cache config?