• Home
  • WordPress
  • web Hosting
  • linux
  • mysql
  • nginx
  • apache2
  • devops

Raju Ginni

wordpress tutorials seo hosting etc

You are here: Home / apache server tutorial (install,config, performance tuning, security, error handling) / Cache control Header & expires headers How to set Properly

Cache control Header & expires headers How to set Properly

Table of Contents

Toggle
  • cache control vs expires headers & if modified since
    • Cache control headers directives Meaning
      • no-cache
      • must-revalidate
      • proxy-revalidate
      • no-store
      • stale-while-revalidate
  • http cache-control header examples Best practices for html & js Css
  •  Add cache control header htaccess apache
  • Add cache control header in Nginx
  • add cahce control header for nginx wordpress sites
  • Cache control header for html files
    • Last-Modified header
    • Remove Expires: Thu, 19 Nov 1981 PHP Header Nginx, Apache, Whatever with root Access
  • Why it’s important to add cache control header?

cache control vs expires headers & if modified since

cache control newer version of expires header.
expires max;
set expiration date to 1984
max expiry date 1 year 365 days 3153600 seconds
Cache-Control: max-age=31536000
304 Not Modified if modified since
(Browser requests to validate the browser cache with server this will done by 304 not modified)
Cache-Control: max-age: 31536000, immutable
immutable not to check server on refresh. een with etag or last modified hash key.
chrome don’t support it, but firefox. Introduced it.
expires header; for older browsers for fallback mechanism.
if modified since helps to provide 304 not modified request when browser requests the server to validate cached resources.
also the googlebot uses it to determine crawl frequency. To reduce load on server by Google bot. example: GoDaddy blocks Googlebot by limiting frequency /rate limiting.
you could see errors in search console.

Cache control headers directives Meaning

Cache-Control: s-maxage=31536000, max-age=86400
s-maxage for CDN & proxies
max-age Remaining for browser.
public  stored by proxy and browser
Private stores only by browser, not cdns/proxy.
no-cache: revalidate cache every time
no-store: don’t store cache browser proxy
no-transform:   don’t rewrite css ex: chrome lite pages
must-revalidate: once cace become stale, has to verify from server.
immutable: explicitly saying don’t need to check server only firefox supports.
max-age=0 equals to no store

no-cache

The no-cache response directive indicates that the response can be stored in caches, but the response must be validated with the origin server before each reuse, even when the cache is disconnected from the origin server.

Cache-Control: no-cache

NO cache vs no store

Note that no-cache does not mean “don’t cache”. no-cache allows caches to store a response but requires them to revalidate it before reuse. If the sense of “don’t cache” that you want is actually “don’t store”, then no-store is the directive to use.

must-revalidate

The must-revalidate response directive indicates that the response can be stored in caches and can be reused while fresh. If the response becomes stale, it must be validated with the origin server before reuse.

Typically, must-revalidate is used with max-age.

Cache-Control: max-age=604800, must-revalidate

proxy-revalidate

The proxy-revalidate response directive is the equivalent of must-revalidate, but specifically for shared caches only.

no-store

The no-store response directive indicates that any caches of any kind (private or shared) should not store this response.

Cache-Control: no-store

stale-while-revalidate

The stale-while-revalidate response directive indicates that the cache could reuse a stale response while it revalidates it to a cache.

Cache-Control: max-age=604800, stale-while-revalidate=86400

In the example above, the response is fresh for 7 days (604800s). After 7 days it becomes stale, but the cache is allowed to reuse it for any requests that are made in the following day (86400s), provided that they revalidate the response in the background.

Revalidation will make the cache be fresh again, so it appears to clients that it was always fresh during that period — effectively hiding the latency penalty of revalidation from them.

If no request happened during that period, the cache became stale and the next request will revalidate normally.


Cache-Control

The Cache-Control general-header field is used to specify directives for caching mechanisms in both, requests and responses. Caching directives are unidirectional, meaning that a given directive in a request is not implying that the same directive is to be given in the response.


Read more at MDN Web Docs

http cache-control header examples Best practices for html & js Css

Html

cache-control no-cache no-store

nginx

Add_header cache-control “no-cache, no-store”;

add_header Cache-Control “s-maxage=864000, max-age=0”;

CDN Server ache validity and browser cache validity 0 seconds means no store.

for html it needs sere from the server. (because no user can read same html page with same content multiple times, even if you updated browser or proxy /cdn seres old page because its expiry set to high.)

2nd reason: browser cache storage space & its validity on users local hard disk. ( most browsers overrides the data if cache limits the space / storage).

Firefox has option to maximum browser cache space, 1GB. chrome it automatically uses available space.

for CSS .JS. Image you can set upto maximum 1 year.

 Add cache control header htaccess apache

<filesMatch “.(css|jpg|jpeg|png|gif|js|ico)$”>
Header set Cache-Control “max-age=31536000, public”
</filesMatch>

Add cache control header in Nginx

location block for static

add_header Cache-Control: s-maxage=31536000, max-age=31536000;
location block html/text
add_header  Cache-Control “s-maxage=31536000, max-age=86400”;
//1 hour
location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico)$
{ expires 15d;
add_header Cache-Control max-age=31536000, “public, no-transform”;}
location ~*  \.(text|css|html)$
{    expires 4h;
add_header Cache-Control: s-maxage=31536000, max-age=86400;
}

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires max;
}

add cahce control header for nginx wordpress sites

in wordpress html files are dynamically generated php, so put add_header or any http headers in php location block.

Cache control header for html files

wordpress content type html text not ends with .html
add_header  Cache-Control “s-maxage=31536000, max-age=86400”;
location ~ /wp-content/cache/.*html$ {
etag on;
add_header Vary “Accept-Encoding, Cookie”;
add_header Cache-Control “no-cache, no-store, must-revalidate”;}
1 hour for browser 10 hours for proxy /cdn
add_header  Cache-Control “s-maxage=864000, max-age=86400”;
cloudflare respects cache control headers
1 year maximum supported date by protocol.

Last-Modified header

automatically generated by servers like nginx, You can disable by empty add headers. it’s up stream server responsibility to provide last modified time.
like $upstream_cache_status.
use php to add last modified header. through fastcgi.
for files from it will adds last modified time. Ex: css.js

Remove Expires: Thu, 19 Nov 1981 PHP Header Nginx, Apache, Whatever with root Access

1 year = 525600 minutes

 

session.cache_limiter = public, max-age=nocache
session.cache_expire = 180
replace with below
session.cache_limiter = public, max-age = 525600
session.cache_expire = 525600

Why it’s important to add cache control header?

to save bandwidth, cpu resources, Faster loading from user local storage.
to indicate proxy servers like cdn.
to communicate with proxy servers load balancing.
tools to check server /website performance.
gtmetrix, pagespeed insights, lighthouse, webpagespeedtest.org.
request headers
if modified since, if none match
also read if modified since, browser caching,  keep alive

apache server tutorial (install,config, performance tuning, security, error handling)

  • what is If-Modified-Since HTTP header how to add to Wordpress website
  • htaccess tutorial tips for wordpress #redirect #leverage browser cache #Gzip #KeepAlive
  • apache modules list (explained, enable disable)
  • connect to server by SSH client Putty SFTP client winscp LAMP, LEMP nginx apache etc linux
  • Lamp stack install on Ubuntu 20.4 LTS apache, mysql, php 7.4(Debian 9 & Ubuntu 18.04 lts)
  • apache performance tuning mpm-worker vs prefork vs event modules
  • enable caching in apache server (mod cache disk cache) vs fastcgi cache
  • how to enable KeepAlive connections in apache nginx wordpress
  • Cache control Header & expires headers How to set Properly
  • apache2 conf sample explained apache configuration file modules etc
  • restart apache in ubuntu (start | stop | reload | config test) centos debian mac linux windows 10 xampp
  • uninstall apache2 ubuntu in 3 steps Debian

hi i am raju ginni, primalry i manage wordpress websites on GCP cloud platform as a cloud engineer, and create content on passionate things.
you can follow me on youtbe

© 2025 - All Rights Reserved Disclaimer & Privacy Policy