There have been four1 major versions of HTTP in-use in the last 30-ish years:

VersionRFCYear
HTTP/1.0RFC 19451996
HTTP/1.1RFC 20681997
HTTP/2RFC 75402015
HTTP/3RFC 91142022

It’s surprising to me how quickly HTTP/1.1 was released after HTTP/1.0. Less than one year!

HTTP/1.0

  • A simple, text-based protocol.
  • Runs over TCP.
  • Only officially supports a single HTTP request and response over each TCP connection, then the connection was torn down.

HTTP/1.1

  • Still a text-based protocol.
  • Added connection re-use.
    • On by default.
    • Controlled via the Connection: keep-alive header and tuned via Keep-Alive.
  • Added the Host header, which allows multiple websites to be hosted at a single IP address.
  • Better cache control mechanisms.
  • Added HTTP pipelining (allowing multiple requests to be sent in succession before responses were received). Apparently never got widespread support, though.
  • Still suffers from Head of Line blocking.
    • Even though TCP connections get re-used, a given request/response cycle must complete before the connection is eligible for re-use.
  • Many browsers improved throughput by allowing up to 6 TCP connections per domain. Websites took this even further with domain sharding.
    • Example: Sharding resources over www1.foo.bar, www2.foo.bar, www3.foo.bar gives you 18 connections to play with.
  • No compression of headers. Lots of redundant data sent for each request/response in the headers, which is inefficient.

HTTP/2

  • Based on pioneering work done by Google with their SPDY (pronounced: “speedy”) protocol in the 2010s.
  • No longer a text-based protocol; now a binary-based protocol.
  • Allows request multiplexing over a single TCP connection.
  • Solved the application-layer Head of Line Blocking problem, but did not solve it for the transport layer (e.g., a dropped TCP packet would still delay all requests/responses behind it).
  • Adds header compression.

HTTP/3

  • Still a binary-based protocol.
  • Moved from TCP to UDP+QUIC for the transport layer. Many improvements come from this.
    • Faster connection setup
      • Old: Setting up a TLS connection with older protocols required around three round trips (3-RTT): the TCP handshake (around 1-RTT) and TLS handshake (2-RTT).
      • New: Setting up a TLS connection with QUIC requires a single round trip (1-RTT) because the transport connection setup and TLS handshakes are merged. Note that 0-RTT resumption is possible with QUIC as well.
    • Avoids the transport-layer head of line blocking problem by using multiple streams. Head of line blocking now fixed at both HTTP and transport layer.
  • Faster connection migration via Connection IDs. (Allows a client to switch networks seamlessly while browsing.)

Closing

It was interesting going down this rabbit hole on HTTP.

I did not know much about HTTP/3 before I started this and I was happy to learn that some of the technologies I remember reading about in in the early 2010s (e.g., SPDY) have matured into something which is now widely used.

I also think that HTTP is a good example of starting a system simple and improving it as you go along. I think it is unlikely that HTTP would have garnered wide-spread support if it had started off complex.2

This Mozilla article has a lot of good information in it.


  1. HTTP/0.9 was also a thing, but never got its own RFC article, so I’m going to ignore it. ↩︎

  2. One of my system design mantras is “start simple and add complexity as needed”. I do not believe it is possible to reliably build complex systems from scratch. It’s often too expensive and you don’t have enough information until you try something in production. ↩︎