80% of end-user response time is spent on the frontend
That’s a bold claim! As a backend developer I frowned upon it thinking “Uh, come on, of course faster database queries matters more!” The quote comes from Steve Souders rules and best practices for making websites faster and is reiterated in his book Even Faster Websites which I spent a fair amount of time diving into over Easter. Here’s some of what I’ve discovered in the world web performance so far.
Even faster requires more work
Souders’ second book on web performance builds on the rules he found during his time at Yahoo. He lists 14 rules that will make your website faster and most of them are so simple to implement its almost silly that not everyone is doing it. They range from the more obvious “Minimise HTTP requests” to more obscure “Configure ETags”. Yahoo maintains an up to date list and good explanations of all the best practices and rules.
Either way, installing the YSlow plugin is straightforward and is a super easy method for determining what you should start focusing on.
The Prince of Performance: Caching
All modern web browsers cache content heavily. The difference between loading a website the first time and second time can be enormous if done right. Aftonbladet.se, for example, is a notoriously bloated site that on the first page load downloads close to 2 Mb of data.
Aftonbladet relies heavily on front-end caches (Varnish) and CDNs. Inspecting the HTTP requests on the second page load, i.e., with the cache primed, most, if not all, images are loaded from my browser’s own cache. There are in other words several layers of caching at play here. A quick look at the HTTP headers reveals the
Cache-Control header which in this case tells the browser to cache the page (the
private directive). It also says that proxies and intermediary caches must not cache the page.
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-UA-Compatible: IE=edge,chrome=1 Content-Type: text/html;charset=utf-8 Vary: Accept-Encoding,X-AB-Device-Type X-Varnish: 1951083729 Via: 1.1 varnish Cache-Control: private,s-maxage=0 Date: Tue, 15 Apr 2014 10:28:40 GMT X-Varnish: 375084195 375015226 Age: 85 Via: 1.1 varnish Connection: keep-alive Set-Cookie: X-AB-Device-Type=desktop; Expires=Wed, 01-Jan-2020 00:00:01 GMT; Path=/; Domain=.aftonbladet.se
Interestingly, this is different for image content which are static and, hence, are more easily cached. The initial response headers from an image has the following header
Cache-Control: public, max-age=3456000. This means that both the browser and intermediate caches should cache the content. Subsequent requests to load the page (and images) include the
If-Modified-Since request header.
GET /image/16729981/76/normal/0156a2cea5d11/johan_hakelius_white.jpg HTTP/1.1 Host: gfx.aftonbladet-cdn.se Connection: keep-alive Cache-Control: max-age=0 Accept: image/webp,*/*;q=0.8 If-Modified-Since: Tue, 28 Jan 2014 13:06:13 GMT User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36 Referer: http://www.aftonbladet.se/ Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8,sv;q=0.6
Content is king
In the end I cannot help but think that these tricks are all irrelevant if we don’t deliver the right content. Souders’ tips are all great given that we know that the content we send in the tubes are right. Even though I’m impressed with Aftonbladet’s development team, I don’t visit their site (other than for technical personal development reasons). And here’s why
They may be the sixth most visited website in Sweden and that entitles, no, forces them to use many web performance tricks, but they are certainly not my top choice given the bloat.
In summary, here is my naive priority list for future high-performance web development:
- Deliver the right content
- Employ best practices
- Cache it
Then you are allowed to focus on the database queries!