CacheControl - danielbodart/webfabric GitHub Wiki

CacheControl directives are a vital part of any website, however developers often disable caching in their browser as the first step of setting up a development machine. This is the worst possible scenario and this filter aims to provide automatic cache control for your whole site so that developers never need to force the cache to expire again.

So instead of disabling caching on every browser the developers uses, just add this filter once to your solution and you are done. If you want to reduce bandwidth usage and increase user responsiveness while still always having the latest content then please also add EtagSupport.

Explanation in detail

This filter tries to balance a number of forces that stop most developers from truly benefiting from the huge investment of caching infrastructure present in most corporate networks, ISP's infrastructure or your hosting environment.

These forces are:

  • Browsers have different default caching rules (Used when the page does not explicitly specify them)
  • Developer ignorance (Disable the cache / add version numbers on the end of URLs)
  • Pressure to deliver quickly (Add caching later)
  • Inconsistent results / bad user experience (Using different caching for JS, CSS and HTML)
  • Support (manual cache expiration)
  • Scalability (cache helps you the most when under heavy load)
  • Security (We must never cache user specific data)

So how do we balance these forces?

  1. By turning the cache on by default
  2. By automatically disabling caching when needed
  3. By providing a small cache time
  4. By making the cache time uniform

On by default caching

The filter adds CacheControl headers to all GET requests by default, eliminating different browser default caching policies. The cache duration is set by the filter init-param seconds but defaults to 60 if not defined.

Automatically disable caching when needed

If any code accesses cookies or session state we know that the request contains user specific logic and so can not be cached. You may notice that your default Servlet always accesses the session (even if it never uses it) there by disabling caching and so we have created the NoSessionState filter to disable this behaviour. This allows your developers to work in safety, without requiring them to change their browser setting to be different from that of a normal user.

Small cache duration

During a previous performance turning session we observed a 700-800% performance increase just by adding a 1 second cache duration to the homepage while under heavy load. This increase in performance only kicked in when the site most needed it, i.e. just after coming to the top of Google PageRank or being linked to by SlashDot etc. Think of this as the useful minimum cache duration. We also observed that when a user edits a page, it takes time for the user to navigate to the original page, click edit, make some changes, submit the results and finally view the updated page. This amount of time can be thought of as the maximum duration we should allow cached responses. We have found that 60 seconds is a good starting point and hence is the default.

Uniform cache duration

One of the problems we often see is HTML, JavaScript and CSS getting out of sync. As we have previously stated even a very small cache time can provide a large increase in responsiveness so there is little value in having complex caching rules that create these inconsistencies. This also eliminates the need to have support or developers create complex systems to invalidate the cache as we know the cache will always be consistent and constantly updating. This also completely eliminates the cache busting practice of adding random numbers on the end of URLs or having complex build processes to do the same.

Ways to increase responsiveness

This filter can and should be used in conjunction with the EtagSupport filter to further reduce bandwidth usage and increase browser responsiveness.

Installation

The current version has been tested with the following jars (older versions should work)

  • scala-library.jar (2.7.7)

Add the following to [web-app]/WEB-INF/web.xml within the web-app tag:

    <filter>
        <filter-name>caching</filter-name>
        <filter-class>org.webfabric.http.CacheControlFilter</filter-class>
        <init-param>
            <param-name>seconds</param-name>
            <param-value>60</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>caching</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
⚠️ **GitHub.com Fallback** ⚠️