Using HTTP/2 Cleartext for a server in Go 1.24
Recorded: May 24, 2026, 8:58 p.m.
| Original | Summarized |
Configuring a Go HTTP Server for Unencrypted HTTP/2 (h2c) | ClarityBossClarityBossCBHomeBlogConfiguring a Go HTTP Server for Unencrypted HTTP/2 (h2c)Configuring a Go HTTP Server for Unencrypted HTTP/2 (h2c)Go 1.24 vastly simplified the configuration of a server that supports HTTP/2 cleartext, no longer requiring non-stdlib packages.I'll give a brief outline of how to enable HTTP/2 cleartext (h2c) in a Go API server when you are using Go 1.24 or newer. This is useful in Cloud Run environments, which handles TLS termination but can take advantage of HTTP/2 features.Dan McGee•May 18, 2026EngineeringIn our application, we use long-lived server-sent event streams (SSE). These are set up to have a really long timeout and lifetime - 15 minutes in our setup. However, Google Cloud Run has a known issue in that client disconnects are not propagated to Cloud Run when using HTTP/1.1 to communicate with the backend service. Thus, I started looking into using HTTP/2 for services.Cloud Run terminates TLS at the frontend, but can forward traffic as either HTTP/1.1 or HTTP/2 cleartext (h2c) traffic. Normally, HTTP/2 always uses TLS, but HTTP clients and servers can often be configured to use a cleartext version of the protocol. Cloud Run also makes you select the protocol to be used. This is basically the “HTTP/2 with Prior Knowledge” setup noted in RFC 9113, section 3.3.Configuring a Go server for HTTP/2 cleartextOur first cut of h2c support predated the Go 1.24 changes I will go into more detail below. Most posts and guides on the internet will point you toward the old outdated approach, but I’ve included it below so it is easier to see the before and after, and migrate your own code if you need to.Before Go 1.24 (old approach)To use h2c, you had to use the golang.org/x/net/http package, and go through a convoluted setup.import ( handler := ... template { # Default is 80; with idle SSE connections, we can easily scale higher. lifecycle { |
The configuration of a Go HTTP server to support unencrypted HTTP/2 cleartext, often referred to as h2c, has evolved significantly with updates to the Go language itself, providing a more streamlined approach for developers. This capability is particularly relevant in environments like Google Cloud Run where TLS termination is handled at the frontend, yet the backend service can benefit from the features of HTTP/2, especially when managing long-lived streams such as Server-Sent Events or SSE, where traditional HTTP/1.1 client disconnect propagation is problematic. Prior to Go version 1.24, enabling h2c support required a more complex setup. Developers had to utilize non-stdlib packages, specifically the golang.org/x/net/http2 and golang.org/x/net/http2/h2c, involving wrapping existing handlers and configuring the http2.Server explicitly through functions like http2.ConfigureServer. This older methodology involved a convoluted process that complicated the integration of standard server settings. With the release of Go 1.24, this process was drastically simplified. The language update integrated native support for configuring protocols directly on the http.Server structure, eliminating the need for external wrappers. The modernized approach allows for the direct setting of protocols on the server instance by configuring the server's protocols object. Specifically, developers can set whether HTTP/1 is enabled and configure the server to set the unencrypted HTTP/2 protocol using the http.Server.Protocols interface. When implementing this feature, the server configuration must also account for various timeouts, such as ReadHeaderTimeout, ReadTimeout, WriteTimeout, and IdleTimeout, which are crucial when dealing with long-lived connections, such as those required by SSE streams. Testing the successful setup locally involves using client tools, such as curl, with the appropriate flag to signal HTTP/2 prior knowledge, ensuring the server is correctly configured for the protocol negotiation. Beyond the server-side implementation, deploying such a service in a platform like Cloud Run requires appropriate container configuration. For services utilizing HTTP/2 cleartext, properly configuring the service environment is necessary to allow the protocol to be utilized. The configuration in Cloud Run involves mapping the necessary ports and adjusting instance settings, such as request concurrency and timeouts, to accommodate the characteristics of the long-lived connections. It is worth noting that the underlying load balancer configuration for HTTPS traffic with Serverless Network Endpoints generally manages the HTTP/2 upgrade negotiation seamlessly, which further simplifies the deployment architecture, as established default timeouts for serverless backends are often more generous than those in traditional setups. This progression allows modern Go applications to leverage advanced protocol features efficiently in cloud-native environments. |