What is a cookie?
Cookies are small pieces of information sent from a web server and stored on your computer. They are used to contain identity and browser state information. They were introduced as a mechanism to get round the fact that HTTP is a stateless protocol. Typically cookies are used for a variety of purposes:
- To identify you and for authentication purposes
- To remember things e.g. what products were placed in your basket?
- Recording past activity e.g. which pages did you visit?
- Record information about you e.g. your preferences
Cookies impact performance because every time you make a request to a web server for an object (e.g. an HTML file, a CSS file, an image) the browser will send the cookie in the request to the server. This means that as your cookie size grows, each request becomes a little bigger and thus performance begins to degrade.
What happens when you set a cookie?
Cookies can be set per domain. Once a cookie has been set, the browser will then transmit this information back to the server for every request that it makes. Say for instance that your page has a cookie header set. When you make requests for objects on the same domain the cookie information gets set along with the request for the file.
Conducting a little experiment…
We took a static copy of a webpage – this included the HTML + assets such as CSS, JS and images.
We then loaded up two copies of this page onto a web server:
- The first version of the page has no cookies set.
- The second version of the page has 4kb of cookies set.
Overall page size: 987kb
Total number of HTTP requests: 90
Total number of HTTP requests served from the primary domain: 39 (the rest were 3rd party tags)
Therefore we can calculate that the additional overhead from requesting the 39 files with 4kb of cookies = 39 x 4 = 156kb.
A tale of two waterfall charts
The results were striking.
When no cookies were set, E2E load time was 7.63 seconds; time to onLoadStart was 6.26 seconds.
When the 4kb cookies were set, E2E load time was 9.16 seconds; time to onLoadStart was 7.89 seconds.
You’ll also notice an interesting pattern in the charts – the chart on the left (with cookies) has much longer green bars. The green bars indicate time to first byte. The majority of this time was spent uploading cookie information to the server for each of the requests that it was making.
One telltale sign of large cookie size is elongated time to first byte bars in your waterfall charts.
Why do cookies cause such a great performance impact?
DSL and Over the Air (GPRS, Edge, HSPA, HSDPA, etc) connections are typically known as asymmetric connections (this gives the “A” in ADSL). This means that the upload bandwidth is different from the download bandwidth. In most cases, ISPs will provide a far greater download bandwidth than they will an upload bandwidth. This means that there can be higher contention for this bandwidth when you are transmitting a lot of data up to the server in order to get a response down from the server.
Typically an 8000 kbps download connection would provide 400 – 1200 kbps of upload bandwidth. Therefore the upload bandwidth can become a big bottleneck in web performance.
Cookies are transmitted with each request on a domain. So if a typical web page is made up of 100 requests, and you transmit 4kb of cookies with each request, you have to transmit 400kb of extra data ON A SLOW UPSTREAM LINK.
This means that there are extra packets involved sending data to the server before a response is received.
How do you determine cookie size?
There are three relatively straightforward ways of determining this:
- Chrome developer tools – gives you a nice running total of the cookie payload.
- Firefox w/ Firebug – the cookie tab shows all cookies but doesn’t give you a total.
- Any other browser: console.log(document.cookie.length);
Recommendations 1 – Minimize cookie size
Encoding too much information in the cookie detrimentally impacts the performance. Minimise the amount of data that is stored in cookies. Keep this to 1kb or less.
If you find yourself storing lots of information in cookies, look instead to make use of alternative mechanisms:
- HTML5 localStorage or sessionStorage, where you need to maintain the state of an application locally.
- Maintain a unique session id and store the user state on the server (using temporary storage controlled by middleware logic i.e. a session table in a database or file).
Recommendation 2 – Consider storing information using web storage
Web storage provides a local browser store for key/value pairs. It can be very handy for maintaining state information on the client side without having to transmit it to the server. Web Storage is a relatively new technology? Is Web Storage ready for prime time? Absolutely!
Recommendation 3 – Setup a cookieless subdomain for serving static assets
Where your cookie size starts growing beyond 1kb in size, setting up a cookieless domain will have a positive performance impact particularly when your pages contain multiple file requests.
- Setup a resource.yourdomain.com subdomain for your local market and use this to access common files across components. This becomes your cookieless domain.
- Move static resources to this domain. Examples include: headers, footers, common stylesheets, common JS including libraries, images etc.
- Set this up according to all the other performance best practices: i.e. gzip, keepalive, minification, caching, SSL tuned, TCP CWND tuned, etc.
- Ideally place a CDN (content delivery network) in front of this so that you accelerate responses from this server, bringing this content close to the end user.