Confused by what the cache-control HTTP header is and how it works with your WordPress site?
In a nutshell, cache-control is an HTTP header that specifies browser caching policies for certain static resources on your website, such as your images. That sounds a little complicated – we know! So if you bear with us, we’ll dig into the topic of cache-control in much greater detail.
In this article, we’ll explain what cache-control is and how it affects behavior on your website. But before we get into the cache-control header, we first need to explain the concept of browser caching.
Here’s what we’ll cover:
- What browser caching is
- What cache-control is and how it works (HTTP headers)
- The different cache-control directives
- How cache-control applies to WordPress/WP Rocket users
Let’s dig in…
What Is Browser Caching?
When someone visits your website for the first time, their web browser needs to request and download every single file to render your page.
However, on subsequent visits, it doesn’t make sense to force them to request and download every single resource on each visit.
For example, your logo probably loads on every single page, but it doesn’t change that often. Forcing a visitor’s browser to re-download your logo for every single page load is just a waste of resources that will slow down your site.
Browser caching lets you avoid that scenario by saving certain types of resources on a visitor’s local computer. Then, a visitor’s browser can load that resource locally rather than re-downloading it, which will speed up your site’s load times and create a better experience for your visitors. This is why you typically see “Leverage browser caching” as a common recommendation in tools like GTmetrix and Pingdom.
In order to enable browser caching, you need to configure your web server so that it tells visitors’ browsers which types of files to store and how long to store them for before re-downloading them.
For example, you can configure your server to say:
“Hey, store JPEG files for one year, but only store PNG files for one month”.
Basically, you set up expiration dates for how long visitors’ browsers should store certain content.
Why add expiration dates at all? Because you want to make sure your visitors still get the most recent version of your page. By setting an expiration date, you’re ensuring that visitors will periodically re-download the relevant resources to ensure an updated experience.
For more, check out our full explanation post on browser caching.
Note – browser caching is a separate strategy from page caching, which is what most people are talking about when they reference “caching” for WordPress. If you’re using WP Rocket, WP Rocket will automatically implement both page caching and browser caching for you – more on this later.
What Is Cache-Control, Then?
Cache-control is one of the main methods to control this browser caching behavior, with the other being expires headers.
Basically, cache-control lets you set these “expiration” dates to control whether a visitor’s browser will load a resource from its local cache or send a request to your site’s web server to download the resource.
It gives you lots of control over how each individual resource behaves and it also lets you control who can cache your content. For example, you can say that a visitor’s browser can cache a certain image, but a CDN (such as Cloudflare) cannot cache it.
More specifically, cache-control is an HTTP header, which brings us to another term that we need to define.
What Are HTTP Headers?
HTTP, short for Hypertext Transfer Protocol, governs how clients and servers communicate. For our purposes, a client is a visitor’s web browser and a server is your WordPress site’s server.
When a client needs a file, it sends a request to the server and the server sends a response to the client.
HTTP headers let clients or servers send additional information with those client requests and server responses. There are different types of HTTP headers, with cache-control being one of them.
Most modern web browsers include developer tools that let you see the HTTP headers associated with every request/response involved in loading a web page.
In Chrome, you can:
- Open developer tools (CTRL + Shift + I)
- Go to the Network tab
- Reload the page
- Select the resource that you want to analyze
- Look at the Headers tab
For example, here are all of the HTTP response headers for loading the featured image for one of WP Rocket’s blog posts:
You can see that cache-control is one of those headers, but there are lots of other headers that communicate additional information. We even added a nice little easter egg in the x-curious header.
HTTP headers can go in both directions. That is, your web browser can attach HTTP headers to the request that it makes to the server, and the server can attach HTTP headers to the response that it sends to the browser.
HTTP headers consist of key-value pairs. The “key” is the part to the left of the colon, while the “value” is the part to the right. More specifically, the value is called the directive for cache-control.
In the example above, the key is “cache-control” and the value/directive is “max-age=31536000” (more on what this means next).
How Does Cache-Control Work?
Ok, at this point you know what browser caching is. You also know that cache-control is one way to control browser caching behavior and that cache-control is an HTTP header that’s passed when a visitor’s browser communicates with your web server.
Now, let’s get into how cache control actually works and the different directives that you can use to control browser caching behavior.
As you learned above, cache-control is a key-value pair that looks something like this:
In this example, the directive is max-age=31536000, but there are other cache-control directives that you can use, and you can also combine multiple directives by using commas.
Let’s go through the most common cache-control directives.
The max-age directive defines how long a browser can reuse the fetched resource before it should download a new resource. The max-age number is in seconds and starts as soon as the request is made.
In this example, the directive is telling a visitor’s browser to use the cached resource for one year from the time of the original request. There are 31,536,000 seconds in one year.
Many cache-control responses will only contain the max-age directive, so you can kind of think of this as the “default” directive.
The max-age directive can be used by both the client and the server.
cache-control: public and cache-control: private
The public and private directives are two opposing directives that control which types of clients can cache resources.
The public directive means that the resource can be stored by any cache. For example, a visitor’s browser, a CDN, etc.
The private directive, on the other hand, means that the resource can still be cached by the visitor’s browser, but it cannot be cached by other intermediate caches, such as a CDN.
You would typically use the private directive for content with user information that you don’t want to be cached by a CDN but are fine with being cached by the visitor’s browser.
The public and private directives are only used by the server in its HTTP response.
The s-maxage directive is similar to max-age, but specifically for shared caches (such as a CDN). It lets you control how long those shared resources can continue to serve a resource from the cache.
For example, if you’re using a CDN, this would be one way to control how long your CDN caches resources (as long as your CDN obeys the directive, which most popular CDNs do).
The s-maxage directive is only used by the server in its HTTP response.
The no-cache directive is somewhat confusing because of the name. It allows any cache to store the response, but the stored response must go through validation with the origin server before using it. That is, a visitor’s browser has to check to make sure that the resource hasn’t changed before using the cached resource.
If you want to completely avoid storing the response in any cache, you actually want to use no-store, which is the next directive that we’ll look at.
The no-cache directive can be used by both the client and the server.
The no-store directive disallows both browsers and intermediate caches from storing the resource. The client will always need to request this asset from the server for every page load.
Typically, you would use this for very sensitive information that you never want to be cached, such as banking information.
The no-store directive can be used by both the client and the server.
Unlike the other directives which can all be used in the server’s HTTP response, the max-stale directive is only used in a client’s request to the server.
The max-stale directive tells a server that the client is willing to accept a response that has exceeded its freshness lifetime by the number in the max-stale directive (in seconds).
WP Rocket and Cache-Control: Do You Need to Do Anything?
If you’re using WP Rocket to speed up your WordPress site, you don’t really need to worry about the cache-control header concepts that we’ve discussed in this article.
WP Rocket automatically implements browser caching using another popular method – expires headers.
WP Rocket enables browser caching (and expires headers) by default as soon as you activate the plugin. It sets up expiration times that are optimal for different types of data – you can view the exact configuration here.
So – if you’re using WP Rocket on your WordPress site, you don’t need to worry about cache-control or expires headers – we take care of it for you as soon as you activate WP Rocket.
You can also use cache-control and expires headers at the same time – they don’t have to be mutually exclusive concepts.
If you’re using WP Rocket, this might come into play if you’re using a CDN to deliver some of your static assets. Many CDNs let you define your own HTTP cache-control headers for resources that you deliver via the CDN.
To finish things out, let’s recap what we’ve covered from the perspective of a WordPress user.
Cache-control is an HTTP header that lets you control how/how long visitors’ browsers (or CDNs) should cache different types of resources on your site.
By caching these resources locally, you can speed up your site’s page load times. However, you don’t want to permanently cache resources, as you also want to ensure that visitors are always seeing the most recent version of your website. Properly implementing browser caching lets you strike the right balance.
There are different directives that you can add to cache-control, but the most “common” directive is max-age, which specifies how long a visitor’s browser should store a resource before requesting it again, in seconds.
If you’re using WP Rocket, you don’t need to worry about cache-control headers because WP Rocket already implements browser caching for you using another popular method – expires headers.
However, you still might encounter cache-control headers if you’re using a CDN with your WordPress site, as most CDNs let you customize the cache-control headers for the resources that you deliver via your CDN.