Improving Site Performance with YSlow

We spend a fair bit of time improving the performance of our application servers and databases, but truth be told 80% of a web request is spent working on the frontend. The screenshot below shows the entire request time of a large eCommerce site using New Relic. (Shown with their permission, of course.). As you can see, the average total request time is 3.2 seconds but only a fraction (5%) is spent in the web app layer (in purple). The other 95% is spent in the network, DOM processing and page render. So looking at performance from the frontend is critical and that’s what we’re going to do in this post.

End User Request Time

YSlow is a tool that helps you analyze the performance of a website based upon 23 best practices. It is available as a browser plugin in Chrome, Firefox, Safari and Opera. It’s also available as a bookmarklet which is ideal for analyzing mobile sites. Or, you can also use it on the command line to process HAR files. The YSlow project is open source and currently maintained by Marcel Duran of Twitter.

The 23 rules that were identified as best practices for Yahoo!’s websites should be considered as guidelines not a strict ruleset. Your website may have different requirements and you should evaluate the rules within your own context. Each rule carries a unique weight, so it will have varying impact on the overall score. You can create a custom ruleset with weights that is better suited to your site. In a follow-up post, we’ll take a look at how to implement your custom configuration with Jenkins to include performance metrics in your build and release cycle.

Getting Started
To get started with YSlow, all you’ll need to do is install one of the browser plugins or the bookmarklet. You can use YSlow on production sites or you can run it against a site running locally. This is perfect to seeing the impact of your changes to your overall score. Run YSlow on any website that you can browse to. Give it a try on some of the big sites like Amazon, Walmart, and ESPN. For this post, I’ll be using the Chrome plugin on Below is a screen shot of the results from the CNN homepage.

YSlow Report on

The page received an overall grade of D with a calculated score of 68. We’ll take a look at the six rules that received a grade of F to see what could be done differently. Along the way you’ll hopefully pickup a few tips and begin to understand the unique characteristics of your site that may need to be adjusted when running YSlow on your own site.

Make Fewer HTTP Requests

Decreasing the number of components on a page reduces the number of HTTP requests required to render the page, resulting in faster page loads. Some ways to reduce the number of components include: combine files, combine multiple scripts into one script, combine multiple CSS files into one style sheet, and use CSS Sprites and image maps.

According to this rule, a site should have no more than three JavaScript files, two CSS stylesheets, and six images within CSS. CNN receives an F on this rule for having 21 JavaScript files, four stylesheets and 29 images used in CSS. Getting your site to include three or fewer JavaScript files is a challenge. Between JavaScript libraries like JQuery, analytics tools like Google Analytics and Gauges, and advertising networks like Google Ads, there is almost no chance your site will meet this requirement. Even Yahoo!’s own frontpage violates the JavaScript component with five scripts.

So if having too many JavaScript files is inevitable, then you should focus on mitigating their impact. To do that, you’ll want to get your JavaScript files out of the critical path. First, put your JavaScript between the closing body and html tags. This allows the majority of your page content to load before the JavaScript files start to download, preventing a blank screen while you wait for them to complete. You’ll also want to have the scripts load asynchronously if possible; services like Google Analytics and many ad networks already do this. Asynchronous loading means you have a very small JavaScript function loaded inline which then calls the main JavaScript functions in a separate thread.

Use a Content Delivery Network

User proximity to web servers impacts response times. Deploying content across multiple geographically dispersed servers helps users perceive that pages are loading faster.

A content delivery network (CDN) allows you to distribute your static assets like images, JavaScript files and stylesheets to geographically distributed servers. This gets the content of your page to your user’s browser faster. Also, using a CDN allows your browser to download the assets for your site on independent threads from the HTML coming direct from your servers. The key to this rule is to train YSlow to understand which (if any) CDNs you use. Many of the external JavaScript services you may be employing are already served on CDNs (or you probably shouldn’t be using them). The benefits from a CDN don’t come for free. You have to worry about expiring the assets when they change. The cleanest method is to append a hash of the file contents to the asset filename, so if the contents change the filename changes. Many frameworks support this method out of the box.

Add Expires Headers

Web pages are becoming increasingly complex with more scripts, style sheets, images and Flash on them. A first-time visit to a page may require several HTTP requests to load all the components. By using Expires headers these components become cacheable, which avoids unnecessary HTTP requests on subsequent page views. Expires headers are most often associated with images, but they can and should be used on all page components including scripts, style sheets and Flash.

Adding Expires headers to your static assets permits the browser to keep a local copy of the file and reuse it, which is generally the use case for those assets. Combine this with the hashing filename scheme from above and you have an extremely light payload on subsequent requests without worrying about old assets wreaking havoc on your site. Adding Expires headers is done in your web server configuration. In Apache you’ll use the ExpiresDefault directive and in nginx you’ll use the expires directive in the HttpHeadersModule.

Reduce DNS Lookups

The Domain Name System (DNS) maps hostnames to IP addresses, just like phonebooks map people’s names to their phone numbers. When you type URL into the browser, the browser contacts a DNS resolver that returns the server’s IP address. DNS has a cost; typically it takes 20 to 120 milliseconds for it to look up the IP address for a hostname. The browser cannot download anything from the host until the lookup completes.

This YSlow rule suggests limiting your page loads to four or fewer domains. Each domain you access requires a DNS resolution which can take precious time. Many sites violate this rule when using a number of third-party services like analytics and advertising networks. If you can delay the load of various components, say social sharing widgets, until after your page loads then this rule becomes less of a concern. A high-quality technique for this is to write your own JavaScript functions that call these third-party services after page load. This allows you to serve the JavaScript from your site (less DNS lookups), as well as build in a circuit-breaker that won’t block the loading of your page if the third-party is not responding.

Configure Entity Tags (ETags)

Entity tags (ETags) are a mechanism web servers and the browser use to determine whether a component in the browser’s cache matches one on the origin server. Since ETags are typically constructed using attributes that make them unique to a specific server hosting a site, the tags will not match when a browser gets the original component from one server and later tries to validate that component on a different server.

If Expires headers are cache control for static assets, think of ETags as cache control for any URL resource. The general principle is that you never want to generate the same resource twice. By using a gateway cache, which sits between the end user and your application server, you can serve the same resource (e.g., rendered HTML fragment) without the effort or reprocessing the entire request. The general flow is end user requests /foo. The application server generates the response for /foo and fingerprints it with an ETag which is stored with the gateway cache. Thirty seconds later, a second user requests /foo and the gateway server forwards the request to the app server with the ETag. The app server determines that the resource hasn’t changed and sends back a 304: Not Modified response instead of the full resource. Then the gateway cache serves the unmodified content it already has. Good use of ETags not only saves time for your users, it can also save you significant money in the number of requests you can serve from an application server.

Use Cookie-Free Domains

When the browser requests a static image and sends cookies with the request, the server ignores the cookies. These cookies are unnecessary network traffic. To workaround this problem, make sure that static components are requested with cookie-free requests by creating a subdomain and hosting them there.

Cookies are the Internet’s way of maintaining state within the stateless protocol of HTTP. Each request is sent with the cookie included, which can be a substantial amount of data depending on your site’s needs. A cookie can easily get to 1k without much effort. This rule is attempting to regulate cookies when they are sent for assets that don’t have any need to know about state, such as images, JavaScript files and stylesheets. If you are serving all of your assets from a CDN (see above), then you can easily get an “A” on this rule as well.

Additional Resources
We’ve only looked at a handful of the rules that complete the YSlow system. Getting to know each of the rules will give you a strong background on best practices for good web performance. Google also maintains a list of performance best practices which is well worth your time.

In the near future, we’ll be looking at how to customize your YSlow ruleset and integrate it into Jenkins so stay tuned. In the meantime, you should probably deploy New Relic and claim your free Data Nerd tshirt.'

View posts by .

Interested in writing for New Relic Blog? Send us a pitch!