Go 1.27 fixes an HTTP/1 bug that silently killed connection reuse
An unread response body used to force a fresh TCP connection on every request. Go's net/http.Transport now drains it automatically, and the Go team's own benchmark shows requests running nearly five times faster.
Go’s standard library has had a quiet performance trap in net/http.Transport: if an HTTP/1 response body isn’t read to completion before Close(), the connection can’t be reused for the next request, because HTTP/1 serves responses sequentially on one stream. Code that only checks a status code, or a JSON decoder that stops right after the closing brace, leaves bytes unread and forces a new connection and TLS handshake every time.
Go 1.27 changes net/http.Transport to drain an unread HTTP/1 response body automatically and asynchronously, up to 50 milliseconds or 256KB, before closing it, skipping the drain when the response carries Connection: close. In the Go team’s own benchmark, calling a simple GET against index.golang.org 100 times took about 710 milliseconds on Go 1.26 versus about 150 milliseconds on Go 1.27, with no code changes required.
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close() // connection now reused even if resp.Body is never read
Why it matters: this is one of the most common accidental performance bugs in Go HTTP clients, and the fix needs no code changes, just upgrading. Anyone who added manual io.Copy(io.Discard, resp.Body) workarounds can drop them.
The caveat: the drain only covers bodies up to 256KB or 50ms of reading; a client that streams a large or slow body without reading it still loses the connection.