Caching HTTP Headers, Cache-Control: max-age

Caching speeds up repeated page views and saves a lot of traffic by preventing downloading of unchanged content every page view.
We can use Cache-Control: max-age=… to inform browser that the component won’t be changed for defined period. This way we avoid unneeded further requests if browser already has the component in its cache and therefore primed-cache page views will be performed faster.
Modern browsers able to cache static files even without any cache control headers using some heuristic methods but they will do it more efficient if we define caching headers implicitly.

For Apache2 you can enable max-age using mod_expires:
ExpiresActive On
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"

For Lighttpd there is mod_expire module. Enable it in server.modules section:
server.modules = (
...
"mod_expire",
...
)
Then add following directives for directories with static files:
$HTTP["url"] =~ "^/images/" {
expire.url = ( "" => "access 30 days" )
}

Max-age for Nginx server can be enabled using ngx_http_headers_module:
expires max;

Now web server sends the caching header for static files:
Cache-Control: max-age=2592000

In case of design change we should prevent using outdated content that browsers have in their caches. This can be done by adding file versions to filenames:
script.js -> script1.js -> script2.js -> ... etc

Cache-control: max-age can be useful also when we output HTML. Imagine pages generated by PHP that changed not so often, once per day or even longer. But browsers still have to download HTML every page view.
We can improve it by sending max-age value in PHP.
header('Cache-Control: max-age=28800');

This way we set desirable cache lifetime to 8 hours. Now if someone is clicking a link for second time within 8 hours period he gets the page instantly.

Max-age also helps to make proxy servers more efficient. We can easily organize transparent server-side caching by adding proxy server to web frontend.

Note that there is not easy case if pages have content that changes often and that’s relevant.
For example, there can be difficulties in caching pages with login form that transforms into some box with «Hello username» after user login or if there are user comments, the user who posted commentary will not see it. Because we cannot ask browser to destroy cache entry, it will still get the old page from cache.
The solution can be using Javascript to generate login box (requires enabled Javascript). If we set a cookie after user logged in, we can check it on client-side and generate suitable content for the logged in user. This way the content will be the same from server side view and can be cached.

37 thoughts on “Caching HTTP Headers, Cache-Control: max-age

  1. Pingback: Using CSS Image Sprites | Web Scaling Blog

  2. It really helps to set far fetched cache-control header.
    But i was looking for cache setting through php, not through apache tweak or htaccess.
    Caching helps saving server, as well as user’s bandwidth.
    But performance remains by far the most important goal for this!
    Thanks for posting.

  3. I’m in charge of web optimization for my company site.
    I will try to add “header(‘Cache-Control: max-age=28800′);” in to the test page, and keep tracking for its index.

  4. The .htaccess code did not work for my site. I do not know why but the “RemoveType application/x-gzip .gz” did not work and I always got the wrong Content-Type for my files.

    I found a solution I want to share. My .taccess code as follows:

    RewriteEngine On
    RewriteBase /cache/assets/
    RewriteCond %{HTTP:Accept-Encoding} .*gzip.*
    RewriteRule (.*)\.css $1.css.gz
    RewriteRule (.*)\.js $1.js.gz
    AddEncoding x-gzip .gz
    ExpiresActive on
    ExpiresDefault A604800
    ExpiresByType text/css “A604800″
    ExpiresByType application/x-javascript “A604800″

    RemoveOutputFilter DEFLATE

    ForceType text/css

    ForceType application/javascript

  5. Pingback: Peter Keating

  6. Pingback: The Need For Speed: Resources To Optimize Site Load Time | Hot Scripts Blog

  7. Pingback: Speed up your site load time to meet expectations of visitors and search engines | Front-end Developer Blog

  8. Well there is lot more to the shopping cart than wholesale hats and caps. If you are a sportsperson you have a variety to make your pick from. Tennis caps, golf and polo hats and caps, baseball and basketball caps, fishing hats and a lot more are here for you. If you wish to flaunt away your style statement on the streets you have a range of trucker hats and visor beanies to chose from. You can get specially

  9. Greetings! This is my first visit to your blog! We are a group of volunteers and starting a
    new initiative in a community in the same niche.
    Your blog provided us useful information to work
    on. You have done a extraordinary job!

    Feel free to visit my site – vu solo cccam yükleme

  10. I just couldn’t leave your web site before suggesting that I extremely loved the usual info an individual supply in your visitors? Is gonna be again incessantly in order to investigate cross-check new posts

  11. I also like the ‘ETAG’ in HTTP, for dynamic files i just include the modification date of the file. And when he come’s back i just compare the ETAG with the new modification date to see if it changed. Like: ETAG = “Type|Key”, so ETAG =”1|[filetime]” could be used for dynamic files. So files that are changed, but not at a special date.

    http://en.wikipedia.org/wiki/HTTP_ETag

  12. Nice post. I was checking continuously this blog and I’m impressed! Extremely helpful info specially the closing phase :) I handle such information a lot. I was looking for this certain information for a long time. Thank you and good luck.

  13. what is the behaviour if cache-control : max-age = -1 is set, should the first request be cached and subsequent requests be revalidates, or all requests should be directly taken from server

  14. I am now not certain where you are getting your information, but great topic.
    I needs to spend some time finding out more or working out more.
    Thanks for magnificent information I was looking for this
    info for my mission.

  15. I am in fact glad to glance at this blog posts which includes
    tons of helpful facts, thanks for providing these information.

  16. I believe this is one of the such a lot significant info for me.
    And i am satisfied reading your article. However should commentary
    on few normal things, The website taste is ideal, the articles is actually
    great : D. Just right job, cheers

  17. I see a lot of interesting posts on your blog. You have to
    spend a lot of time writing, i know how to save you a lot of time, there is a tool that creates unique, google
    friendly articles in couple of seconds, just search in google
    - laranita’s free content source

  18. Fantastic site you have here but I was wondering if you knew
    of any community forums that cover the same topics discussed here?
    I’d really love to be a part of online community
    where I can get advice from other experienced individuals
    that share the same interest. If you have any
    suggestions, please let me know. Bless you!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>