Rails 5 adds http_cache_forever

Abhishek Jain

By Abhishek Jain

on March 4, 2016

This blog is part of our  Rails 5 series.

Rails 5 allows to cache HTTP responses forever by introducing http_cache_forever method.

Sometimes, we have static pages that never/rarely change.

2# app/controllers/home_controller.rb
3class HomeController < ApplicationController
4  def index
5    render
6  end
9# app/views/home/index.html.erb

Let's see log for the above action.

2Processing by HomeController#index as HTML
3  Rendered home/index.html.erb within layouts/application (1.3ms)
4Completed 200 OK in 224ms (Views: 212.4ms | ActiveRecord: 0.0ms)
6 And so on for every request for this action.

There is no change in the response and still we are rendering same thing again and again and again.

Rails 5 introduces http_cache_forever

When response does not change then we want browsers and proxies to cache it for a long time.

Method http_cache_forever allows us to set response headers to tell browsers and proxies that response has not modified.

2# app/controllers/home_controller.rb
3class HomeController < ApplicationController
4  def index
5    http_cache_forever(public: true) {}
6  end
9# OR
10class HomeController < ApplicationController
11  def index
12    http_cache_forever(public: true) do
13      render
14    end
15  end
19# app/views/home/index.html.erb

Now let's look at the log for the modified code.

2# When request is made for the first time.
4Processing by HomeController#index as HTML
5  Rendered home/index.html.erb within layouts/application (1.3ms)
6Completed 200 OK in 224ms (Views: 212.4ms | ActiveRecord: 0.0ms)
8# For consecutive requests for the same page
10Processing by HomeController#index as HTML
11Completed 304 Not Modified in 2ms (ActiveRecord: 0.0ms)

On first hit, we serve the request normally but, then on each subsequent request cache is revalidated and a "304 Not Modified" response is sent to the browser.

Options with http_cache_forever

By default, HTTP responses are cached only on the user's web browser. To allow proxies to cache the response, we can set public to true to indicate that they can serve the cached response.

Use http_cache_forever with caution

By using this method, Cache-Control: max-age=3155760000 is set as response header and browser/proxy won't revalidate the resource back to the server unless force reload is done.

In case force reload is done, Cache-Control: max-age=0 is set as request header.

In this case, browser will receive the changed resource whether ETag is changed or not.

http_cache_forever is literally going to set the headers to cache it for 100 years and developers would have to take extra steps to revalidate it. So, this should be used with extra care.