Idea about Expires header

Since the Steve Sounder’s High Performance Web Sites everyone knows to set far future Expires header on their static assets. What he didn’t say was how to deal with the file changes. You can’t instruct browser to download the file so you actually have to change the file’s URL.

Ruby on Rails handles this by automatically adding file’s timestamp as a query-string when using build-in helper methods — simple and not requiring server-side URLs rewriting. This is good enough, but only for files accessed from HTML directly and doesn’t work for files accessed from CSS: background images (unless you have dynamically generated styles).

I was thinking for some time about those background images, because they can be heavy and if you’re not using CSS sprites they make lots of requests. As I don’t like dynamically generated style sheets, I didn’t want any additional processing. And so it came to me: why not incorporate some changing value into the domain name? You could put a revision number or a timestamp in domain name of your statics server, just like this: static-1566.example.com. Both Rails and Django provide easy ways to change static assets domain.

This requires you to set-up wildcard subdomain, but is’s easier than processing CSS files. It works because url function in a style sheet is resolved using the style sheet’s own address.

PS: This is only a brain-dump — I didn’t test it.

10 Comments so far

  1. pstradomski on October 18th, 2009

    Might be easier to just version a path.

    eg : /static-1234/style.css, /static-1234/image.png
    and then reference the image as url(‘./image.png’) from the stylesheet. No need for wildcard domains (which are often inaccessible).

    Great idea anyway. Might try to implement it.

  2. oinopion on October 18th, 2009

    I was thinking about Google App Engine (again!). GAE gives you wildcard subdomains for free and AFAIK doesn’t allow synlinks. But for dedicated servers versioned path might be better.

  3. lbadura on October 19th, 2009

    It’s an interesting idea. Have you tried implementing it in one of your
    applications ?

  4. oinopion on October 19th, 2009

    @lbadura: No, not yet. I’ll be trying that in some time for my brand new application I’m developing as my Honours Project.

  5. Mekk on October 21st, 2009

    I am just patching URLs manually when appropriate (linking to
    /some/thing-13.png or /other/style-21.css and using nginx rewrite rule to strip -(\d ) from static files), and don’t find it too troublesome, but I guess it depends on the application.

    Your idea is interesting, but I find one drawback. When does this number in domain name change? If it is common for all files, then even resources which were not changed would need to be redownloaded. If it is different for every image/file, then there are no chances for keepalive connection, and the browser may hog your server as the limit of 2 connections to one address does not apply.

    PS There always is a possibility to patch the urls using version control hooks or build script hooks….

  6. oinopion on October 21st, 2009

    Editing URLs by hand is tedious and can be forgotten (especially when one image is used in many places). Passing it to VCS hook requires writing some more or less sophisticated script and that’s as good as writing patch for Less (CSS preprocessor) to do that. And yes, my solution would force downloading every component after one change. I don’t say your hints are bad or my solution is better, it just happens that I have different priorities.

  7. pstradomski on November 2nd, 2009

    Tried it on the development version of KSM site (though with url prefix, not domain prefix). Works like a charm – most pages now require just a single request to fetch HTML, everything else is cached.

  8. oinopion on November 2nd, 2009

    Nice to hear that!

  9. Scott on February 17th, 2010

    We went with versioning the path and updating it based on the revision number in a Subversion repository. There’s different ways to do it, but this is automatic and working well for us

    http://www.redrobotstudios.com/blog/2008/12/18/versioned-media-and-expires-headers-in-django/

  10. kwalo on March 25th, 2010

    Yet another recipe to serve static media in Django: http://www.peterbe.com/plog/serve-your-static-stuff-in-django-with-nginx

Leave a Reply