Company Logo

Bisht Bytes

Overview of HTTP/1.1 Waterfall and HTTP/2 multiplexing

Published On: 20 Sep 2024
Reading Time: 8 minutes

Overview


Let's dive deeper into the "waterfall effect" in HTTP/1.1, how it occurs, and how it contrasts with HTTP/2.

Waterfall Effect in HTTP/1.1

In HTTP/1.1, each request-response pair typically uses the following sequence of events over a single connection:

  • Step 1: The client sends an HTTP request (e.g., an HTML file).
  • Step 2: The server processes the request and sends back a response.
  • Step 3: The client parses the response and identifies other resources it needs (e.g., CSS, JavaScript, images).
  • Step 4: The client requests these resources one by one, sequentially.

If you look at a browser’s network tab when loading a page using HTTP/1.1, you’ll see the resources being loaded in a sequential manner, with each resource waiting for the previous one to finish. This sequential loading looks like a "waterfall" in the timeline view.

Example Scenario in HTTP/1.1

Imagine a webpage with the following resources:

  • An HTML file (index.html)
  • A CSS file (styles.css)
  • Two JavaScript files (app.js and vendor.js)
  • Three images (image1.jpg, image2.jpg, image3.jpg)

In HTTP/1.1, a typical flow might look like this:

  1. Request index.html
    The client requests the main HTML page from the server.

    Time: 100ms to download.

    The browser can't make further requests until it receives and parses the HTML file to know which other resources are needed.

  2. Request styles.css
    After receiving index.html, the client parses it and discovers the styles.css file.

    Time: 150ms to download.

    The browser can't request the next resource until it gets the CSS.

  3. Request app.js and vendor.js
    Once styles.css is downloaded, the browser can request the JavaScript files.

    Time: 200ms for app.js, 100ms for vendor.js.

  4. Request images
    After the scripts are processed, the client requests the images sequentially.

    Time: 100ms for each image.

Each of these requests blocks the next, creating a waterfall effect where each subsequent request has to wait until the prior one completes. Even though the client might be able to open multiple connections (typically 6), the ordering of dependencies (e.g., HTML before CSS, CSS before JS) leads to a serialization of requests.

Head-of-Line Blocking in HTTP/1.1

HTTP/1.1 suffers from head-of-line blocking, meaning that if one request in a sequence takes a long time (e.g., downloading a large image), the following requests are delayed. For example, if one of the images takes 500ms instead of 100ms, all subsequent requests have to wait for that image to finish.

Example Waterfall in HTTP/1.1

Let’s say the following resources have these load times:

  • index.html → 100ms
  • styles.css → 150ms
  • app.js → 200ms
  • vendor.js → 100ms
  • image1.jpg → 100ms
  • image2.jpg → 100ms
  • image3.jpg → 100ms

Here’s a simplified representation of the waterfall:

100ms (index.html)  --> 150ms (styles.css) --> 200ms (app.js)  --> 100ms (vendor.js) --> 100ms (image1) --> 100ms (image2) --> 100ms (image3)

In total, this takes 850ms to load all resources. Each subsequent resource is requested only when the prior one completes.

How HTTP/2 Fixes This

HTTP/2 introduces multiplexing, which allows multiple requests and responses to be sent over a single connection concurrently. This removes the head-of-line blocking and eliminates the waterfall effect.

In HTTP/2:

  • The browser can send multiple requests (e.g., for styles.css, app.js, and the images) at the same time without waiting for previous requests to complete.
  • Each request is split into smaller frames and sent over the same TCP connection, with the server sending responses in parallel.

Example Scenario in HTTP/2

With the same resources as before:

  • index.html → 100ms
  • styles.css → 150ms
  • app.js → 200ms
  • vendor.js → 100ms
  • image1.jpg → 100ms
  • image2.jpg → 100ms
  • image3.jpg → 100ms

In HTTP/2, the client can request all of these resources at the same time. The browser doesn’t have to wait for the HTML file to download before requesting the CSS or images.

Here's how the request flow looks in HTTP/2:

index.html -->  styles.css, app.js, vendor.js, image1, image2, image3

Even though each resource has different download times, all of them can be requested concurrently. The browser might still have to prioritize certain resources (e.g., HTML before CSS), but the overall time is reduced because multiple resources are being fetched simultaneously.

In this example, the longest resource is app.js (200ms), so instead of the 850ms it took in HTTP/1.1, the total load time for HTTP/2 would be just 200ms, the time of the longest resource download.

Visualization of HTTP/1.1 vs HTTP/2

  • HTTP/1.1:
100ms (HTML)
  --> 150ms (CSS)
      --> 200ms (JS)
          --> 100ms (Images)
  • HTTP/2:
Request all resources at once
Total time = 200ms (longest request)

Additional HTTP/2 Features

  • Header Compression: HTTP/2 reduces the overhead of sending redundant headers, further improving performance.
  • Server Push: The server can proactively push resources (like CSS or JavaScript) to the client without waiting for the client to request them, further reducing latency.

Conclusion

The "waterfall" in HTTP/1.1 occurs due to its sequential, blocking nature when sending requests over a connection. Each request must wait for the previous one to complete before it can be processed, creating cascading delays. HTTP/2 improves this by allowing multiple requests and responses to happen concurrently over the same connection, significantly reducing loading times and eliminating the waterfall effect.


Page Views: -