There have been four1 major versions of HTTP in-use in the last 30-ish years:
Version | RFC | Year |
---|---|---|
HTTP/1.0 | RFC 1945 | 1996 |
HTTP/1.1 | RFC 2068 | 1997 |
HTTP/2 | RFC 7540 | 2015 |
HTTP/3 | RFC 9114 | 2022 |
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 viaKeep-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 setup
- 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.
HTTP/0.9 was also a thing, but never got its own RFC article, so I’m going to ignore it. ↩︎
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. ↩︎