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.

# app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    render
  end
end

# app/views/home/index.html.erb
<h1>Welcome</h1>

Let’s see log for the above action.

Processing by HomeController#index as HTML
  Rendered home/index.html.erb within layouts/application (1.3ms)
Completed 200 OK in 224ms (Views: 212.4ms | ActiveRecord: 0.0ms)

 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.

# app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    http_cache_forever(public: true) {}
  end
end

# OR
class HomeController < ApplicationController
  def index
    http_cache_forever(public: true) do
      render
    end
  end
end


# app/views/home/index.html.erb
<h1>Welcome</h1>

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

# When request is made for the first time.

Processing by HomeController#index as HTML
  Rendered home/index.html.erb within layouts/application (1.3ms)
Completed 200 OK in 224ms (Views: 212.4ms | ActiveRecord: 0.0ms)

# For consecutive requests for the same page

Processing by HomeController#index as HTML
Completed 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.