PIMP MY IDEBack to garage
Go 1.27 / HTTP clients / 14 Oct 2026

Close the body. Keep the socket.

Go 1.27 repairs a quiet HTTP/1 performance trap with a bounded background drain. The new behavior helps reuse. It does not promise reuse.

One unread byte can cost a connection

An HTTP/1 client cannot find the next response on a connection until it reaches the end of the current response body. Closing a body without reading it forced Go through 1.26 to abandon that connection. A JSON decoder could trigger the same result by leaving one trailing newline unread.

The bug-shaped lesson is about framing, not cleanup style.

Go 1.27 changes net/http.Transport. When an HTTP/1 response body closes with unread content, the transport can drain up to 256 KiB for up to 50 milliseconds in the background. If the drain finishes before another request needs the connection, the transport can reuse it. If it does not finish, the next request can open another connection.

Do less, but measure again

The Go team now recommends closing the body when the caller no longer needs it. Hand-written drain helpers are no longer the default answer for Go 1.27. The transport also skips the drain when a response says Connection: close. HTTP/2 does not need this fix because it separates responses into multiplexed streams.

The Go blog reports a status-only test that fell from about 710 milliseconds on Go 1.26 to about 150 milliseconds on Go 1.27. That result came from one machine, one endpoint, and forced HTTP/1. Treat it as a reason to rerun your own client workload, not a universal five-times claim.

Review the client around the fix

Reuse the Transport instead of creating one per request. Keep idle-connection limits deliberate. Record the negotiated protocol in the test. Measure connection creation with httptrace or server logs. Then compare Go versions against the same endpoint and response sizes.

Interactive control / response-body route

HTTP reuse drain dyno

Select a Go version and one HTTP/1 body state. The dyno explains the documented route and drafts a test card. It does not send requests or predict your latency.

Runtime detent
HTTP/1 response state
Documented routeBounded drain can recover reuse

Go 1.27 can drain the unread HTTP/1 tail in the background. Reuse depends on the drain finishing before the connection is needed again.

This teaching control restates documented branches. It does not inspect a client, contact a server, or verify connection reuse.
Sources read

Evidence rack

Mechanism and measured example

Go blog: Better HTTP/1 connection reuse

Documents the framing problem, 256 KiB and 50 millisecond limits, protocol boundary, skip conditions, and the authors' benchmark.

Read the Go blog
Release contract

Go 1.27 release notes

Records automatic bounded draining for unread HTTP/1 response bodies and the idle-connection configuration caveat.

Read the release notes
Transport contract

net/http Transport documentation

Documents connection caching, idle limits, protocol selection, concurrent safety, and the instruction to reuse transports.

Read the package docs
Discovery route

Hacker News item 50090369

The official HN API maps the current discussion to the Go post. Discussion score is not evidence about runtime performance.

Read the discussion