NGINX: HTTP/2 vs HTTP/3 β€” What Actually Changes Under the Hood?

HTTP/2 and HTTP/3 both improve web performance, but use fundamentally different transports. HTTP/2 runs over TCP, while HTTP/3 uses QUIC over UDPβ€”changing connection handling, packet processing, streams, congestion control, and NGINX worker behavior.

NGINX: HTTP/2 vs HTTP/3 β€” What Actually Changes Under the Hood?
Photo by Krystian PiΔ…tek / Unsplash


HTTP/2 and HTTP/3 were both designed to make the modern web faster, but they take fundamentally different approaches to transporting HTTP traffic.

If you run NGINX, the distinction is especially important because enabling HTTP/3 is not simply a matter of changing http2 to http3. HTTP/2 runs over TCP, while HTTP/3 runs over QUIC, which runs over UDP.

That difference changes the connection model, packet handling, congestion control, stream behavior, and even how NGINX workers can process incoming traffic.

HTTP/2: HTTP Multiplexing Over TCP

HTTP/1.1 traditionally required multiple connections or techniques such as pipelining to efficiently retrieve many resources.

HTTP/2 changed that model.

Instead of treating every request as an independent connection, HTTP/2 uses a single TCP connection containing multiple streams, which are independent logical channels used to carry individual requests and responses concurrently.

In essence:

                    TCP CONNECTION
                         β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚              β”‚              β”‚
       Stream 1       Stream 3       Stream 5
          β”‚              β”‚              β”‚
       HTML            CSS             JS

This is called multiplexing.

A browser can request the HTML document, CSS, JavaScript, images, fonts, and other resources concurrently over the same connection.

NGINX therefore does not need a separate TCP connection for every HTTP/2 request.

A simplified NGINX configuration looks like:

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    http2 on;

    server_name example.com;

    ssl_certificate     /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    ...
}

The important part is:

http2 on;

http2 on; enables HTTP/2 for the server block. It tells NGINX that clients connecting to that server over HTTPS may use HTTP/2 instead of HTTP/1.1, provided the client supports it and TLS negotiation selects HTTP/2.

The connection itself is still TCP.

Client
   β”‚
   β”‚ HTTPS
   β”‚ TCP
   β–Ό
NGINX :443
   β”‚
   └── HTTP/2
       β”œβ”€β”€ Stream 1 β†’ Request / Response
       β”œβ”€β”€ Stream 3 β†’ Request / Response
       β”œβ”€β”€ Stream 5 β†’ Request / Response
       └── Stream 7 β†’ Request / Response

The TCP connection remains the underlying transport. HTTP/2 changes how HTTP messages are multiplexed over that connection.

What http2 on;actually changes

Without HTTP/2:

HTTPS
  β”‚
  β–Ό
TCP connection
  β”‚
  └── HTTP/1.1 requests

One important point

http2 on; does not mean β€œuse HTTP/2 only.”

A client that doesn’t support HTTP/2 can still connect using HTTP/1.1. During the TLS handshake, ALPN is used to negotiate the protocol.

In essence:

                 TLS + ALPN
                     β”‚
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
             β–Ό               β–Ό
         HTTP/2           HTTP/1.1
             β”‚
       TCP connection

HTTP/2 = TCP + HTTP/2 streams

The HTTP/2 Problem: TCP Head-of-Line Blocking

HTTP/2 solved a major problem with HTTP/1.1, but it inherited a limitation from TCP.

TCP presents applications with an ordered byte stream.

HTTP/2 solved a major problem with HTTP/1.1 by allowing multiple requests and responses to share a single connection. However, it inherited an important limitation from the TCP transport underneath it.

TCP presents applications with a single, ordered byte stream. Data can arrive out of order at the network level, but TCP must reassemble that data and deliver the byte stream to the application in order.

Consider an HTTP/2 connection carrying several independent streams:

                 ONE TCP CONNECTION
══════════════════════════════════════════════════════►

   Stream A ────────[A1][A2][A3][A4]──────────────►
   Stream B ────────[B1][B2][B3][B4]──────────────►
   Stream C ────────[C1][C2][C3][C4]──────────────►
   Stream D ────────[D1][D2][D3][D4]──────────────►
                         β–²
                         β”‚
                    TCP data lost

Suppose the TCP segment containing part of Stream A is lost. Data belonging to Streams B, C, and D may still reach the server successfully, but TCP cannot simply deliver bytes beyond the missing portion to the application while maintaining its required ordered byte stream.

The later data can be received and buffered, but the missing data must be recovered before TCP can provide a continuous stream to the application.

This creates TCP-level head-of-line (HOL) blocking.

The important point is that HTTP/2 streams are logically independent, but TCP does not know about those streams. From TCP’s perspective, everything is simply part of one ordered byte stream.

HTTP/2 therefore provides excellent multiplexing at the HTTP layer, but all of those streams ultimately depend on the same TCP connection.

HTTP/3 takes a fundamentally different approach by moving stream multiplexing into QUIC, where streams are independently managed at the transport layer.

HTTP/3: HTTP Over QUIC

HTTP/3 does not run over TCP.

It runs over QUIC, and QUIC runs over UDP.

The stack becomes:

HTTP/3
   β”‚
   β–Ό
 QUIC
   β”‚
   β–Ό
 UDP
   β”‚
   β–Ό
 IP

Instead of:

HTTP/2
   β”‚
   β–Ό
 TLS
   β”‚
   β–Ό
 TCP
   β”‚
   β–Ό
 IP


This is the most important architectural difference between HTTP/2 and HTTP/3.

HTTP/2 relies on TCP for transport and uses TLS as a separate security layer, while HTTP/3 uses QUIC as its secure, multiplexed transport over UDP.


QUIC Is More Than β€œUDP”

It is tempting to describe HTTP/3 as simply β€œHTTP over UDP.”

That is technically true at a very low level, but it misses the important part.

UDP itself does not provide:

  • reliable delivery
  • ordering
  • congestion control
  • connection management
  • retransmission
  • encrypted transport

QUIC implements these capabilities above UDP. It provides a modern, encrypted transport layer while using UDP as its underlying datagram mechanism.

So the architecture is better understood as:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           HTTP/3             β”‚
β”‚     HTTP semantics           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚            QUIC              β”‚
β”‚  Streams                     β”‚
β”‚  Reliable delivery           β”‚
β”‚  Retransmission              β”‚
β”‚  Flow control                β”‚
β”‚  Congestion control          β”‚
β”‚  Connection management       β”‚
β”‚  TLS 1.3 integration         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             UDP              β”‚
β”‚       Datagram transport     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             IP               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

UDP provides the basic datagram transport. QUIC builds the sophisticated transport functionality on top of it, and HTTP/3 runs on top of QUIC.

That distinction is essential: HTTP/3 is not β€œHTTP directly over UDP.” It is HTTP/3 over QUIC over UDP.

HTTP/3 Streams Are Independent

This is one of the most important differences between HTTP/2 and HTTP/3.

HTTP/3 uses QUIC streams, and each stream has its own ordered delivery. A packet loss affecting one stream does not necessarily block unrelated streams from continuing.

In essence:

                    QUIC CONNECTION
                           β”‚
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚             β”‚             β”‚
          Stream 1      Stream 3      Stream 5
             β”‚             β”‚             β”‚
           HTML           CSS            JS
             β”‚             β”‚             β”‚
             β–Ό             X             β–Ό
          received      packet loss    received
                           β”‚
                           β”‚
                      retransmit
                           β”‚
                           β–Ό
                       CSS data

Suppose a QUIC packet carrying part of the CSS stream is lost. QUIC can detect the loss and retransmit the missing data, while data belonging to the HTML and JavaScript streams can continue to be delivered if it has arrived successfully.

The browser therefore does not necessarily have to wait for the missing CSS data before receiving additional data from unrelated streams.

This is a major architectural advantage of QUIC: loss on one stream does not inherently create transport-level head-of-line blocking for every other stream in the connection.

That is fundamentally different from HTTP/2 over TCP, where all HTTP/2 streams share the same ordered TCP byte stream.

So, What’s the Fuzz?

Okay, we know how HTTP/3 works.
But what’s the big deal?

Going deep into QUIC internals, packet recovery, congestion control, and connection migration is beyond the scope of this article. The important takeaway is that HTTP/3 gives the web a modern transport layer designed to reduce latency, handle packet loss more gracefully, and keep connections moving efficiently.

But this isn’t just theoretical.

What Websites Use QUIC?

QUIC already powers a growing part of the modern web through HTTP/3. Major platformsβ€”including SNUBmonkeyβ„’, Google, YouTube, Facebook, and sites using CDNs like Cloudflareβ€”support it.

QUIC isn’t waiting for the future. The future is already using it.

What matters is what HTTP/3 can actually do for real-world applications:

1. Better on Bad Networks

HTTP/3 handles packet loss more efficiently, so a problem with one stream doesn’t necessarily slow down the others.

2. Better for Mobile

Cellular networks can be unpredictable. HTTP/3 is designed to handle latency, packet loss, congestion, and changing network conditions more efficiently.

3. Faster Connections

QUIC combines transport setup and TLS 1.3, reducing the time needed to establish a secure connection.

4. Survives Network Changes

QUIC can keep a connection alive when a device switches networks, such as moving from Wi-Fi to cellular.

5. Less Head-of-Line Blocking

In HTTP/2, multiple requests share one TCP connection. If a packet is lost, TCP may hold up data that arrived after itβ€”even if that data belongs to a different request.

6. Great for Modern Apps

APIs, streaming, large downloads, live updates, and other applications with multiple simultaneous data flows can benefit from QUIC’s stream architecture.

7. HTTP/2 Still Has a Place

HTTP/3 doesn’t replace HTTP/2 overnight. NGINX can serve both:

TCP :443  β†’ HTTP/2
UDP :443  β†’ HTTP/3 / QUIC

Clients that support HTTP/3 can use QUIC, while everyone else can continue using HTTP/2.

The Point?

HTTP/3 isn’t simply β€œfaster HTTP.”

It’s about making applications more responsive and resilient when the network isn’t perfect.

That’s the real fuzz.

HTTP/3 isn’t about replacing HTTP/2β€”it’s about building a more resilient, modern transport for today’s web. The real benefits show up when networks are slow, lossy, congested, or constantly changing.

Thanks for readingβ€”and as always, keep experimenting, breaking things safely, and learning.

See you on the next one.

Keep Us Caffeinated  β¦Ώ β¦Ώ
Spotify Logo
↑
SNUBmonkey Join our 36K+ readers