HTTP/1.0 was finalized in 1996. Every request to the same server requires a separate TCP connection which is expensive to establish.
HTTP/1.1 (1997) introduced ๐—ฝ๐—ฒ๐—ฟ๐˜€๐—ถ๐˜€๐˜๐—ฒ๐—ป๐˜ ๐—ฐ๐—ผ๐—ป๐—ป๐—ฒ๐—ฐ๐˜๐—ถ๐—ผ๐—ป๐˜€, which allow a TCP connection to be reused for multiple requests and responses. This reduces the latency in setting up new connections for each request. But HTTP/1.1 doesnโ€™t solve the ๐—ต๐—ฒ๐—ฎ๐—ฑ-๐—ผ๐—ณ-๐—น๐—ถ๐—ป๐—ฒ (๐—›๐—ข๐—Ÿ) ๐—ฏ๐—น๐—ผ๐—ฐ๐—ธ๐—ถ๐—ป๐—ด problem.
Although HTTP/1.1 enabled pipelining, where multiple requests could be sent out without waiting for each response, the responses still had to be processed and sent back in the order the requests were received. This ordering requirement caused HOL blocking - if the first request took a long time, all later requests had to wait.
HTTP/2 (2015) introduced ๐—›๐—ง๐—ง๐—ฃ ๐˜€๐˜๐—ฟ๐—ฒ๐—ฎ๐—บ๐˜€ - an abstraction that allows ๐—บ๐˜‚๐—น๐˜๐—ถ๐—ฝ๐—น๐—ฒ๐˜…๐—ถ๐—ป๐—ด different HTTP exchanges onto the same TCP connection. Streams donโ€™t need to be sent in order. This eliminates HOL blocking at the application layer. But HOL still exists at the TCP transport layer.
HTTP/3 draft was published in 2020. It uses ๐—ค๐—จ๐—œ๐—– instead of TCP as the ๐˜๐—ฟ๐—ฎ๐—ป๐˜€๐—ฝ๐—ผ๐—ฟ๐˜ ๐—ฝ๐—ฟ๐—ผ๐˜๐—ผ๐—ฐ๐—ผ๐—น, removing HOL blocking in the transport layer.
QUIC uses UDP. It introduces ๐˜€๐˜๐—ฟ๐—ฒ๐—ฎ๐—บ๐˜€ at the transport layer. QUIC streams share one connection, so no new handshakes or slow starts are necessary to create new streams. QUIC streams are delivered independently so packet loss usually doesnโ€™t affect other streams.