How to configure cache control headers in NGINX

Contents

Caching is the procedure of storing downloaded data for later use, where they can be read from disk instead of requesting them again. Making proper use of your browser and CDN caching can significantly speed up your web portal.

How does caching work?

Each user's browser has a built-in cache, which stores static objects downloaded from websites. The next time they connect, if the object they are requesting is still in the cache, will be loaded from memory instead of requesting it again, which will significantly speed up the performance and reduce the load on your web server in the procedure.

The user's browser is a client-side cache. Despite this, many large sites will also use a content delivery network or CDN. The CDN sits in front of your web server and caches your pages on the server side, generally across multiple edge servers located around the world. This improves access latency, performance and greatly reduces stress on your web server. For more information on CDNs, you can read our guide here.

Cache-Control is a header that you can configure your web server to add to all outgoing requests. When using it, you can specify which resources are cached and for how long. Despite this, there are a few things to pay attention to before adding it to the whole site.

Some pages should Never be cached. Anything that requires a user to log in should not be cached by a CDN, otherwise you will run the risk show a user's personal information to others. You can still cache these kinds of pages only on the browser side (Setting Cache-Control for private). As a general rule, if the page is going to be exactly the same for all users, as your home page, can cache it. Static resources, like CSS and images, can generally be cached, often for much longer.

You will also want to make sure you determine reasonable lifetime values. (TTL) for each resource. TTL controls how long the object will stay in the cache before being invalidated, prompting the user to request a new object. The trade-off here is between a long caching time and quick updates.. You don't want to cache your home page for a whole year, because I could be changing something on Tuesday. Determining a maximum age of a few minutes for your home page is long enough to cover immediate reloads and fast enough to allow rapid spread of updates.. Despite this, for static resources like images, it is possible that they never change, and it should be fine setting high TTL values, even as high as two years.

You can always use versioned filenames to trigger a cache reload. If you publish a new version of a CSS stylesheet, you can name it styles-1.0.1.css, and the user's browser (and any CDN in front of it) you will see it as a new file that needs to be downloaded again. At the same time, for some CDNs, you can issue manual overrides to flush the existing cache without changing any file names.

How to use Cache-Control in NGINX

Cache-Control you have some options:

  • public – Anyone can cache it, including browsers and CDN. Use this for most static objects.
  • private – Contains sensitive data that cannot be cached through CDNs or reverse proxies. The user's browser can cache it locally. Use this for most authenticated pages.
  • no-cache – Despite the name, don't disable caching. The browser can still cache the solution for performance, but you must check with the origin server for updates before using it. Use this if you want the user to revalidate every time
  • no-store – Disable caching completely. Use this only for highly confidential data that should not be submitted twice.

When setting the max-age, always done in seconds. Despite this, NGINX enables some more custom values:

  • -1, O off, which will disable caching and not modify existing headers
  • epoch, set to Unix time zero, which will explicitly disable caching and purge all caches (useful if you are using NGINX as a reverse proxy)
  • max, that will expire when the universe ends, the 31 from December to 2037
  • 30s, for seconds
  • 1m, per minute
  • 24h, for hours
  • 3d, for days
  • 1M, for months
  • 2y, during years

At the same time, you can add the no-transform directive, which disables any conversion that can be carried out on the resource. As an example, some CDNs compress images to reduce bandwidth. This directive disables that behavior.

Para NGINX, You can modify the Cache-Control headers with the following directives:

expires 1and;
add_header Cache-Control "public, no-transform";

The first line sets the maximum age in 1 year and the second establishes the public and no-transform caching settings. You can add this to a server block to apply site wide, but a better method is to match the file extensions to a location block to determine different values ​​based on the file extension:

location ~* .(?:css|js)$ {
  expires 1and;
  add_header Cache-Control "public";
}

This location block uses a regular expression match, denoted by the ~. This is useful for applying general settings for the content type. If you want to make exceptions for specific locations, you can use a normal location block, which will take precedence over a regex match.

location /profile {
    expires 2d;
    add_header Cache-Control "public, no-transform";
}

You can also use the = modifier, which matches the paths exactly and will take precedence over a regex match and standard location block.

Use Surrogate-Control to modify CDN behavior

Although you can disable CDN caching and still take advantage of browser caching using Cache-Control: private, it is better to have direct control over it. Most CDNs will respect the Surrogate-Control header, which works exactly the same as Cache-Control, except it's only intended for CDN. Thus, you can tell Fastly to do one thing and the user to do another.

And NGINX, you will have to configure this header manually and configure the max-age value instead of using NGINX expires directive.

add_header Surrogate-Control "public, max-age=86400";
add_header Cache-Control "public, max-age=120";

You will definitely want to test with your CDN to verify that this works.Surrogate-Control it's fairly new and it's not universal.

Subscribe to our Newsletter

We will not send you SPAM mail. We hate it as much as you.