up

Zoompf's Web Performance Blog

Note: Archived Content

This is the archived version of the Zoompf blog. Since our acquisition by Rigor, all our new research and posts on web performance are being published on The Rigor Blog

The Many Kinds of SPOF

 Billy Hoffman on March 4, 2013. Category: Guide

If there is one good thing about disasters it is that they tend to raise awareness and increase preparedness. For example, if I hear about a house fire, I always go and check the batteries in my smoke detectors. If a bad storm hits somewhere, I always go and test the flashlights in the house to make sure they are working properly. We should use disasters as an opportunity to check if we are vulnerable and plan how we would respond.

Over the weekend, CloudFlare had a router configuration problem. Many websites use CloudFlare to proxy all of their web traffic to optimize content on the fly. Accelerator solutions like CloudFlare can only work by requiring that all your visitors are accessing to your website via CloudFlare, this creates a giant single point of failure. When CloudFlare failed, 785,000 sites disappearing off the Internet and could not be accessed.

CloudFlare Zoompf failure

This event provides a perfect opportunity to review your web application for points of failure. In front-end web development, there are several area’s that are single points of failure you need to be away of. In this post, I focus exclusively on single points of failure (SPOF) facing front-end developers. Specifically:

  • Third Party Content
  • JavaScript CDNs
  • Content CDNs
  • Accelerators

I will leave IT operational points of failure such as web servers and databases for later.

Third Party Content

As we all know loading third party content can be the source of many performance problems. However loading badly behaving third party content can also be a source of failure for your website. Consider code like this:

<html>
<head>
<script src="//example.com/analytics.js"></script>
</head>
<body>
Important Content.
</body>
</html>

What happens if example.com is having problems? Or is loading slowly? What if the connection hangs? Or the connection is made over SSL and the SSL negotiation has problems? Or any number of other problems? All your isers will stare at a blank white screen, and the browser will not download anything else, while it awaits downloading that analytics package.

Linking to content like JavaScript libraries, fonts, and CSS all create single points of failure. This content is different than images, since it plays a part in how and when a browser will render content. Failures here can completely alter or significantly delay you page load times.

For JavaScript files, the solution is to use asynchronous loading whenever possible. Isolate widgets into <iframes> to delay their impact. Fonts and CSS are a little more complex and SPOF is an evolving subject still receiving a lot of research. Be sure to check out the work of Steve Souders as well as tools like SPOFCheck to learn more solutions.

JavaScript CDNs

JavaScript CDNs are centrally hosted copies of commonly used JavaScript libraries like jQuery. The concept is that why should every website serve you a copy of jQuery? If everyone linked to a common version stored on a hostname, visitors to your website might already have the file cached.

Unfortunately, JavaScript CDNs don’t really work very well, for reasons I have discussed at length in the past and as others have shown more recently. They don’t often provide any front-end performance gain.

Additionally, they create a SPOF. So you are adding a SPOF for a “performance improvement” with no proof of efficacy. Worse, if they do fail, your website will most likely be completely nonfunctional, as the type of libraries linked to on JavaScript CDNs are core libraries to a website such as jQuery or MooTools. In short, you should avoid JavaScript CDNs entirely.

But if you must…

You can at least recover slightly from SPOF with JavaScript CDN. You cannot prevent the potentially huge impact to page load times. However you can ensure that, if the loading of a core library like jQuery from a JavaScript CDN fails, that your website instead loads a locally hosted copy. For example:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.5.1.min.js">\x3C/script>')</script>

With this code, you first link to the copy of jQuery on the JavaScript CDN. A following <script> block checks to see if certain global variables loaded by the library are present. Should the library fail to load, these checks fail, and the code writes out another <script> tag which points to a locally hosted copy. This thread on Stack Overflow provides additional details.

Content CDNs

I am a big believer in using wrapper functions to output the HTML tags for content like images, CSS, and JavaScript. In other words I try to avoid writing out tags in my HTML templates or dynamically generated pages such as:

<img src="/images/logo.png" width="200" height="50" alt="Zoompf logo" />

and instead do:

<% =Splat.Image("/images/logo.png", "Zoompf logo"); %>

This function actually writes out the <img> tag. Moving the creation of the tag into code provides a lot of benefits:

  • Automatically add file versioning into the URL for the resource to enable far future caching.
  • Automatically minify relevant content.
  • Automatically add different subdomains to do domain sharding where needed.
  • For images, I can check the image’s actual width/height and insert those attributes into the resulting tag.

Another benefit of using wrapper functions is the control this provides over CDNs. By CDNs, I mean companies like Akamai or CacheFly which improve website performance by serving content from nearby systems to reduce latency. CDNs will use special host names to download content and resolves those DNS names to be servers that are physically near your visitor.

But what if your CDN is experiencing problems? Or your CFO forgot to pay your CDN bill? Suddenly the host names that those resources are served from are not resolving or not properly responding with your content? What are you to do?

By using wrapper functions, you can quickly work around the failure. Your Splat.Image() or Splat.CSS() functions can simply write out URLs that point to your host system instead of the CDN. As soon as CDN problems develop, a flag in a config file on your production website could tell those Splat.* functions to stop using CDN urls. You can respond to the failure instantly, without waiting for DNS records to populate. This allows you to have the benefits of a CDN without the bottlenecks.

Wrapper functions are also a great way to bypass the third party content problems or JavaScript CDN problems. If your font provider is having issues, a single configuration change could tell your Splat.CSS() function to not include references to custom fonts. Wrapper functions can also easily insert JavaScript CDN fallback code, or completely bypass the use of JavaScript CDNs entirely and use local copies.

In short, wrapper functions give you an easy injection point to rapidly change how your site references content and work around failures.

Accelerators

Unfortunately cloud accelerators like CloudFlare require that your website’s traffic go through them. Typically your DNS settings have been changed so that, from the Internets perspective, you no longer control www.site.com, the accelerator does. These solutions are often described as a “CDN” but that’s really not the case. The wrapper functions solution discussed above only works because the requests for HTML pages are still coming directly to your website. You are simply linking to urls in your HTML and you can decide where those links go (to a CDN, to local resources, etc).

With a cloud accelerator, you don’t get that chance. No visitors are getting your HTML, so there is nothing to work around. Additionally, changing your DNS settings to point www.site.com back to your website really won’t solve the problem since DNS changes can take hours or even days to propagate.

To avoid a cloud accelerator as a single point of failure which cannot be worked around, consider not using these services. After all, you can locally install free and open source software on your web server to apply the same “on-the-fly” optimizations as an accelerator. Apache’s mod_pagespeed from Google, and nginx’s ngx_pagespeed are two such examples. Many hosting providers (such as Dreamhost) offer these optimization modules pre-installed. You can use scripts like SiteCrunch can optimize all your images. This becomes even more powerful as a reoccurring task or as part of your build and deploy process. Content Management Systems like WordPress, Dupral, and TYPO3 all have a rich ecosystem of free plug-ins which can automatically optimize your website.

In short, there are a lot of options to automatically optimize content. Dodging the responsibility to improve your website’s performance by funneling all your traffic through a third party is a drastic and often unnecessary step.

Summary

There are many ways the front-end of a website can fail. Third party content which affects how the page is render can completely disrupt your website. JavaScript CDNs can fail, depriving you of core client-side functionality and leading to additional errors. CDNs delivering static content can fail, leaving you without any resources. Finally, proxy services like accelerators can fail, completely removing all access to your website from the Internet.

All of these failure points were added to the front-end to help web performance or add additional functionality. It is important to review whether you are actually getting any performance benefit for the added risk. It is also important to have in place a plan to resolve these issues, such as using wrapper functions to bypass the troubled area.

Comments

Have some thoughts, a comment, or some feedback? Talk to us on Twitter @zoompf or use our contact us form.