QUIC is already faster than TCP for most realistic internet workloads, even before you consider its built-in encryption.
Let’s see it in action. Imagine a simple web server serving a single HTML file with a few embedded images. With TCP, the client initiates a three-way handshake, then a TLS handshake, and then starts requesting the file. The server sends the file, but if any packet gets lost, the entire connection stalls until that packet is retransmitted.
# Simulate TCP connection and data transfer (simplified)
# On Server:
nc -l -p 8080 > received_data.txt
# On Client:
echo "GET /index.html HTTP/1.1\r\nHost: example.com\r\n\r\n" | nc example.com 8080
# (Imagine data flowing, and then a packet loss simulation)
QUIC, built on UDP, sidesteps many of these TCP limitations. It combines the connection and encryption handshakes into a single round trip (1-RTT or even 0-RTT for returning connections). Crucially, QUIC handles multiple independent streams within a single connection. If a packet is lost for one stream (say, an image), only that specific stream is blocked, while other streams (like the HTML file itself) can continue to be delivered.
Here’s a conceptual look at how QUIC handles streams:
QUIC Connection ID: 12345
Stream 1 (HTML): Packet 1 (Seq 1) -> Packet 2 (Seq 2) -> ...
Stream 2 (Image A): Packet 1 (Seq 1) -> Packet 2 (Seq 2) -> ...
Stream 3 (Image B): Packet 1 (Seq 1) -> Packet 2 (Seq 2) -> ...
If Packet 2 for Stream 2 is lost:
Stream 1 continues: Packet 3 (Seq 3) arrives.
Stream 3 continues: Packet 3 (Seq 3) arrives.
Stream 2 waits for retransmission of Packet 2 (Seq 2).
The problem QUIC solves is primarily the "Head-of-Line Blocking" inherent in TCP. With TCP, if you request multiple resources (like an HTML file and its associated images) over a single connection, and a packet for any one of those resources gets lost, the entire connection waits. This means even if the HTML file’s packets are arriving perfectly, you won’t see them until the lost packet for an image is retransmitted. This is a major bottleneck on lossy networks.
QUIC’s internal multiplexing with independent streams breaks this dependency. Each stream is treated as a separate logical flow, and packet loss in one doesn’t impact others. This dramatically improves perceived performance, especially for web pages with many small assets.
The exact levers you control with QUIC are less about low-level network parameters and more about connection management and the application-level behavior. You configure the QUIC endpoint (server or client) with certificates for TLS, specify the UDP port, and the QUIC stack handles the rest. The application logic then interacts with QUIC streams, opening and closing them as needed for different resources.
What many people don’t realize is that QUIC’s congestion control is pluggable and often more sophisticated than traditional TCP algorithms. While TCP has been stuck with variants of Reno or Cubic for years, QUIC implementations can easily adopt newer, more aggressive, or more stable algorithms like BBR or even custom ones, tuned for specific network conditions. This allows QUIC to recover faster from congestion and utilize available bandwidth more effectively.
The next major hurdle for QUIC adoption will be navigating the complexities of middleboxes and firewalls that are still heavily optimized for TCP and may block or misinterpret UDP traffic.