HTTP/2 in Go

Updated

September 8, 2026

HTTP/2 in Go

Overview

Go’s net/http speaks HTTP/2 when TLS+ALPN (or h2c in limited cases) allows it. One TCP connection multiplexes streams, changing connection pool math and failure modes.

Diagram: multiplex

regions: single TLS conn
flow:
  [Client]
       |
       v
  [conn]

  [conn]
       |
       v
  [Server]

Client knobs

tr := &http.Transport{
    ForceAttemptHTTP2: true,
    // MaxIdleConnsPerHost less critical for h2 multiplexing
    // but MaxConnsPerHost still bounds total conns
}
GODEBUG=http2debug=1 ./app   # noisy; debug only

Practical differences vs HTTP/1.1

Topic HTTP/1.1 HTTP/2
Parallel requests / host many conns or pipeline rare streams on one conn
Head-of-line per connection TCP HOL stream independence (TCP still HOL)
Server push N/A / deprecated paths limited/rare in Go clients
Debugging simple need h2 frames / debug flags

Server

http.Server + TLS config with NextProtos often enough. Timeouts still mandatory:

ReadHeaderTimeout, ReadTimeout, WriteTimeout, IdleTimeout

Experiment

go run .
# curl -v --http2 https://...
// print negotiated protocol from a real client response
// resp.Proto == "HTTP/2.0" when h2 used

What to notice: Idle pool settings interact with h2 differently; leaking Body still kills reuse.

Try next: Load test one host with many parallel requests; compare conn count h2 vs forced h1.