// Engineering Log
HTTP, HTTPS, and TLS: Part 3 — HTTP/1.1, HTTP/2, and HTTP/3: how the versions differ
Published on 2026-09-30
// Fast route
This article belongs to the topic Servers and infrastructure.
HTTP has three versions in active use: HTTP/1.1, HTTP/2, and HTTP/3. Methods, headers, and status codes are the same across them, so an application usually doesn’t care which version a request arrived with. The difference is how messages are framed and transmitted over the network, and this determines page load speed with dozens of resources and behavior on poor mobile connections.
HTTP/1.1
The 1997 version (now — RFC 9112). Messages are text, and the TCP connection is kept open between requests (keep-alive).
The main limitation is queuing. You cannot send a second request on a single connection until the response to the first arrives. The pipelining mechanism that allowed sending several requests in a row existed in the standard, but responses still had to come in order, and one slow image would delay everything else. Browsers never enabled it.
Workarounds from the HTTP/1.1 era:
- up to six connections to one host in the browser;
- domain sharding — serving static files from
static1.example.ru,static2.example.ruto get more connections; - concatenating scripts and styles into a single file, image sprites.
Each new connection is a TCP and TLS handshake, a separate TCP slow start, and extra load on the server.
HTTP/2
The 2015 standard (now — RFC 9113), grown out of Google’s SPDY protocol.
Binary frames instead of text. A message is split into frames: a header frame, data frames. Each frame is marked with a stream identifier.
Multiplexing. Dozens of streams run concurrently over one TCP connection, one per request. Frames from different responses are interleaved, and a slow response does not hold others. One connection per site is enough for the browser, and domain sharding and file concatenation become unnecessary and even harmful: multiple domains mean multiple connections and DNS lookups.
HPACK header compression. In HTTP/1.1 each request retransmits User-Agent, Cookie, Accept — hundreds of bytes repeated request to request. HPACK keeps a table of previously sent headers on both sides and sends only references to it.
Pseudo-headers. The start line is replaced by fields :method, :path, :scheme, :authority (instead of Host) in requests and :status in responses. All header names are lowercase.
Server push — the server sends resources the client hasn’t yet asked for. In practice it rarely saved anything, and Chrome disabled it in version 106 (2022). Instead of push people use the 103 Early Hints response and <link rel="preload">.
TLS only in browsers. The standard allows HTTP/2 without encryption (h2c), but no browser supports it. The version is negotiated during the TLS handshake via the ALPN extension: the client offers h2, http/1.1, the server chooses. h2c is seen in internal networks, for example in gRPC between services.
A remaining problem. Multiplexing removed queuing at the HTTP level, but not at the TCP level. TCP delivers bytes strictly in order, and if one packet is lost, all streams in the connection wait for its retransmission, even those whose data wasn’t in it. This is called head-of-line blocking. On a stable channel it’s unnoticeable, but with 1–2% losses on mobile networks HTTP/2 over a single connection can perform worse than HTTP/1.1 with six connections.
HTTP/3 and QUIC
HTTP/3 (RFC 9114, 2022) runs over QUIC (RFC 9000) — a transport protocol on UDP that took over tasks of TCP and TLS.
Transport-level streams. QUIC is aware of streams itself, and a lost packet delays only the stream whose data was in it. Head-of-line blocking disappears.
TLS 1.3 is built-in. Encryption is mandatory in QUIC; there is no separate TLS handshake over the transport — keys are agreed in the first QUIC packets. A new connection is established in one round trip (1-RTT) instead of two for TCP + TLS 1.3; a resumed connection can send data immediately (0-RTT). Transport-level fields that are visible to everyone in TCP — packet numbers, acknowledgements — are encrypted too.
Connection migration. A QUIC connection is identified not by an IP/port pair but by a connection ID. When a phone switches from Wi-Fi to mobile, downloads continue without a new handshake.
QPACK header compression — a variant of HPACK adapted to out-of-order streams.
How the browser learns about HTTP/3. The first connection to a site goes over TCP (HTTP/2 or 1.1). The server advertises HTTP/3 support with a header:
alt-svc: h3=":443"; ma=86400and the browser will try QUIC on UDP port 443 for subsequent requests. The other way is an HTTPS DNS record with the parameter alpn="h3": then the browser may go to HTTP/3 immediately.
Limitations. UDP/443 is closed in some corporate networks, and in some networks QUIC is blocked or deliberately slowed. Browsers in that case silently fall back to TCP, so HTTP/3 is always enabled in addition to HTTP/2, not instead of it. Implementing QUIC in user space consumes more CPU on the server than TCP in the kernel.
Summary table
| HTTP/1.1 | HTTP/2 | HTTP/3 | |
|---|---|---|---|
| Transport | TCP | TCP | QUIC (UDP) |
| Format | text | binary frames | binary frames |
| Requests per connection concurrently | 1 | many | many |
| Header compression | none | HPACK | QPACK |
| Encryption | optional | mandatory in browsers | always, TLS 1.3 |
| Packet loss delays | one connection | all streams in the connection | only the affected stream |
| Version negotiation | by default | ALPN h2 | Alt-Svc or DNS HTTPS, ALPN h3 |
Enabling in Nginx
HTTP/2 in Nginx 1.25.1 and newer is enabled with a separate directive (the old form listen 443 ssl http2 is deprecated). HTTP/3 is via listen ... quic; the ngx_http_v3_module is included in official packages from nginx.org starting with 1.25:
server {
listen 443 ssl;
listen 443 quic reuseport; # reuseport — only in one server block per port
listen [::]:443 ssl;
listen [::]:443 quic reuseport;
http2 on;
http3 on;
server_name example.ru;
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3; # TLSv1.3 is required for QUIC
add_header Alt-Svc 'h3=":443"; ma=86400' always;
}Don’t forget to open UDP/443 in the firewall — this is the most common reason HTTP/3 “doesn’t enable”:
ufw allow 443/udpCaddy enables HTTP/2 and HTTP/3 automatically, without configuration. HAProxy has HTTP/3 since version 2.6 (bind quic4@:443 ssl crt ... alpn h3).
How to check the version
curl shows the negotiated version in the -v output and in the http_version variable:
curl -sI --http2 https://example.ru/ -o /dev/null -w '%{http_version}\n'
# 2
curl -sI --http3 https://example.ru/ -o /dev/null -w '%{http_version}\n'
# 3 — if curl is built with HTTP/3 supportWhether your curl supports HTTP/3 is visible in the Features line of curl --version output (the word HTTP3). The system curl in macOS and many distributions is built without it. You can test with a Docker image where curl is built with HTTP/3, or via a browser: in developer tools on the Network tab enable the Protocol column — it will show h2 or h3.
The --http3 flag tries QUIC but also starts a parallel TCP attempt and falls back to it if QUIC doesn’t respond. To test QUIC only without fallback, use --http3-only.
Common mistakes
- HTTP/3 is enabled in the config, but UDP/443 is closed on the server or by the hoster — browsers silently stay on HTTP/2.
reuseportis specified in multipleserverblocks for the same address — Nginx won’t start with an error about a duplicated parameter.- Internal services behind a proxy expect HTTP/2 (gRPC), but the proxy connects to them over HTTP/1.1 — in Nginx you need
grpc_pass, notproxy_pass. - Concatenating all scripts into one huge file out of habit from HTTP/1.1 — with HTTP/2 small files load in parallel and are better cached separately.
// Similar task
If you are dealing with something similar
This article belongs to one of the main working topics. You can keep reading on the topic, go to the homepage to understand what I do, or open the service pages directly.
Article topic
Servers and infrastructure
VPS, Linux, web stack, migrations, hosting, databases, and core operations.
Typical tasks behind this topic
- Move a site or service to a new server
- Set up Linux, Nginx, databases, and backups
- Figure out why the system behaves unstably
// Next step
If you need help with this topic, not just another article, it is better to go straight to the service page. The homepage and topic collection stay available as secondary routes.
Open services// Reviews
Related reviews
Thanks to Mikhail for his responsiveness. We spoke by phone; he explained how I could do it myself. This is my second time reaching out — everything’s great and prompt.
Thanks to Mikhail for his responsiveness. We had a call; he explained how I could do it myself. This is my second time contacting him; everything is great and prompt.
Consultation on Nginx Proxy Manager and Portainer
2025-02-25 · ★ 5/5
I want to express my deep gratitude to the specialist who set up SEO-friendly URLs for me on OpenCart. Configuring them turned out to be easy and simple, and I'm glad I finally found a professional who did everything well and without unnecessary complications. Before this I went through four specialists, and each time there were issues with the setup, but this person handled the task perfectly.
I want to express my great gratitude to the specialist who configured SEO-friendly URLs for me on OpenCart. Setting up the URLs turned out to be easy and simple, and I'm glad that I finally found a professional who did …
Excellent work — this isn't the first time I've used them; they find solutions to complex problems. I recommend.
Excellent work, this isn't my first time contacting them; they find solutions to complex problems. I recommend.
Excellent work! He completed the assigned task on time and without errors. It was a pleasure to work with him; I recommend him.
Great job! Completed the assigned task on time and without errors. It was a pleasure to work together, I recommend.
Excellent specialist — he delved into the problem, figured it out, and fixed it. I recommend him.
Excellent specialist, delved into the problem, figured it out, and fixed it. I recommend.
I needed to resolve an SSL certificate issue on a server where the certificate had been issued through Nginx Proxy Manager. Mikhail clarified all the details of my setup and requested access to assess the feasibility of solving the issue, since he hadn't worked with that service before. He quickly figured it out and fixed my problem. Perfect cooperation)
I needed to solve an issue with an SSL certificate on the server that was issued through Ngnix Proxy manager. Mikhail clarified all the details of how everything is set up for me, asked for access to assess the …
Diagnosing Nginx Proxy Manager in a Docker container and resolving the issue
2024-03-15 · ★ 5/5
// Contact
Need help?
Get in touch with me and I'll help solve the problem
I reply within one business day (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related