Recommended cache headers provided by HTTP/1.1:
- “Expires” or “Cache-Control: max-age“
- “Last-Modified” or “ETag“
“Expires” and “Cache-Control: max-age”
These headers specify the time period during which the browser can use the cached resource without checking if a new version is available in the web server. I recommend “Expires” over “Cache-Control: max-age” cause is more widely supported.
Never use “Expires” and “Cache-Control: max-age” at the same time, that would be redundant.
“Last-Modified” and “ETag”
These specify some properties about the resource to determine if the files are the same or have been updated. In the “Last-Modified” header is a date. In the “ETag” header could be any value that uniquely identifies the resource (usually is a content hash). Generaly “Etag” is the recommended header over “Last-Modified“, however “ETag” is not recommended on Balanced environments because the apache server generates the Etag hashes taking into account information from the running server, which means that each server will generate different Etags.
Never use “Etag” and “Last-Modified” at the same time, that would be redundant.
The recommended configuration
The best configuration would be setting the “Expires” header to 1 year (the maximum value) and using “Etag” based on the files size and last modified time. In apache you can archive this using adding this to your apache configuration file /etc/httpd/conf.d/
FileETag MTime Size
In order to make it work in a balanced environment you would need to deploy your project in such a way that the last modified time of a file is exactly the same on all servers.
The other way
You can dinamically enable caching adding fingerprints in the paths to the resources (images, css, js files… ) The fingerprint should only change when the file has been updated, this way the browsers will refetch that source everytime it has been modified.