How to make websites fly

One of the pillars of UX is to have a website that loads QUICKLY. So how does one go about delivering one's content as quickly as possible?

by Hagen - November 2015

One of the pillars of UX is to have a website that loads QUICKLY. Speed matters - just look at the now famous study showing how "one second could cost Amazon billions in sales". Google also plays a massive role in rewarding fast-loading sites. Since its advent, Google has prioritised delivering results at breakneck speed, and in recent years has been using site speed as a ranking factor. So how does one go about delivering one's content as quickly as possible?

Any discussion with regards to website speed should be split into front end and back end considerations.

Front end

Front end optimisation refers to tweaks made in HTML/CSS/JavaScript and how they are served by the web server. These tweaks are typically the easiest and most obvious way to boost a website's performance, given how advanced most browsers are nowadays in terms of optimising and caching; and results are decent, though less than dramatic.

The easiest way to optimise the front end is to install the excellent YSlow plugin and to run a test on your website. Without going through every suggestion they make, here are some comments on a few:

  • Use a CDN (we like CacheFly). If your site has even just a small amount of international traffic, you should consider offloading your assets onto a CDN. If your site is not on a CDN and your client runs it through a site speed checker, don't be alarmed if the result is something along the lines of "Your site is slower than 87% of websites tested". This is because the test is typically being done from Europe or America, which means that every image and file has to be delivered via the relatively tiny pipes that connect South Africa to the rest of the world. So if you're not using a CDN, these tests are not a reflection of the site speed for South African browsers. If you offload your assets to a CDN, you will see an immediate and major improvement when using site speed check tools like Pingdom.
  • Otherwise, you definitely want to:
    • Put JavaScript at the bottom.
    • Minify JavaScript and CSS. Grunt is a useful tool for this that you should consider using.
    • Make sure you are serving images in the size that they need to be and not scaled in CSS. If you can't be bothered to develop resizing functionality (it’s not that easy) and have some spare cash to throw at the problem, Cloudinary's responsive library is seriously good and will do a better job than anyone else.
    • Add Expires headers to your assets. If you use a CDN, make sure you set the expiry to a future date via the CDN admin panel. Manage versioning and cache invalidation via the query string. (If this sounds like Greek to you, send me a tweet and I'll elaborate).

Yslow gives you about 22 things to work through, but if you're going to do anything, do the above first. Many of the other suggestions can be safely ignored. Coaxing an additional 10 milliseconds of performance out of a website is probably not worth it unless you have budget to burn.

Back end

Back end optimisation is about digging into the heart of code base, database and server and is best left to the experts. If a website is struggling with performance, this is typically where the most impact can be made. You can tweak the front end using the suggestions above until you're blue in the face, but if the back end is not optimised or has an issue, it won't make much of a difference.

The tweaking that is available to you also depends on what development framework you're using. If you are using a framework such as CakePHP or Laravel, you will have more options available to you than you would when using a pre-built CMS like Wordpress or Expression Engine.

Here are some thoughts on this.

Start with the database

Tweak MySQL, but be wary. Many a novice has made the mistake of changing a MySQL config variable without understanding exactly what it means. When in doubt, change nothing except the key_buffer_size when using MyISAM and innodb_buffer_pool_size / innodb_buffer_pool_instances when using InnoDB databases. If you use both, adjust both. Touch the rest at your peril.

If a website has issues, it's often due to slow SQL queries. Debug this by enabling slow query logging and queries with no indexes. Take a look at the queries being logged and fix them one by one, either by rewriting them or merely by adding the necessary indexes. Sometimes a few indexes are all that's needed, so much so that we've had new developers exclaiming "it's like magic!" when seeing the performance improvements achieved by adding an index onto a table column.

Most public facing websites are significantly more read intensive than write intensive, so it's typically a good idea to cache your database queries using something like Memcached. This is particularly easy to do when using a custom framework such as CakePHP. Cache invalidation is a tricky subject though, spawning concepts with fantastic names such as the Thundering Herd problem. Notwithstanding this, even if you set the cache to refresh after a few minutes, it will still make a significant difference under load.

What else

Additionally, you could cache pages. Here I'm not referring to query caching, but full page caching, where a dynamic page is built once and then served from Cache (until invalidated). If one has a mostly "read only" site that receives high load, look no further than Varnish. It is a seriously impressive and popular piece of technology that is used by many high traffic sites world over. When developing in ExpressionEngine, we always make use of CE Cache, which lets entire pages be served either as static HTML files or via Memcached. Again, one has to plan cache invalidation carefully.

If you want to seriously throw the kitchen sink at a problem, consider using PHP 7 or HHVM if your code base doesn't run on PHP 7. HHVM, originally called Hip Hop, was created by Facebook to coax more performance out of PHP. It is simple to install and most PHP frameworks will run fine on it. On the code bases that we run, we have seen up to 400% improvement in throughput. It especially shines under load. Another instance that had some exclaiming "it's like magic!".

Wrapping up

The above is not an exhaustive list, but to my mind, contains the main things to spend time and effort on. When one can't do everything, it's best to spend time on those things that have the most impact. Want to add something? Send me a tweet.