HTTPS Works but HTTP/2 Does Not: Inspect ALPN Negotiation

Check client protocol offers, TLS termination and proxy-to-origin behavior when HTTPS succeeds but the expected HTTP/2 connection is not actually negotiated.

In this article

A successful HTTPS connection does not prove that HTTP/2 was negotiated. Check the application's protocol on each connection boundary: client to edge, edge to proxy, and proxy to origin where those are separate. One leg can use HTTP/2 while another uses HTTP/1.1.

RFC 7301 defines ALPN as a mechanism for selecting an application protocol during TLS negotiation. The practical diagnostic is to compare what the client offers, what the TLS endpoint supports, and what was actually selected, without confusing those observations with certificate validity.

Establish the symptom precisely

Record the exact hostname, client version, request path, and network route. “The server supports HTTP/2” may mean a configuration contains an enabled setting, not that this request used it. Keep intended capability and observed protocol separate.

Inspect a real request with the client's supported developer or diagnostic tools. Record the negotiated protocol rather than inferring it from a response header or the presence of HTTPS in the URL. A library built without a needed capability may behave differently from a browser on the same machine.

Check whether the symptom is failure, fallback, or simply an unexpected observation. A working HTTP/1.1 response can be acceptable for one product and a blocker for another. Define the requirement before treating fallback as an outage.

Locate TLS termination

Draw the actual connection boundaries. If a CDN terminates the user's TLS session, that endpoint negotiates with the user. The origin's settings may govern a different connection and cannot by themselves prove what the user received.

Include internal proxies and service gateways if they terminate and re-establish TLS. Record which team owns each configuration. A change at the origin can leave the edge behavior unchanged, while a changed edge policy can alter the user's protocol without any application deployment.

Keep server-name selection in view. A shared endpoint can host several names with different settings. Testing an IP address without the intended hostname can exercise a default virtual host rather than the service that users reach.

Use a read-only handshake check

For an authorized public endpoint, a diagnostic might use:

sh
openssl s_client -connect service.example.com:443 \
  -servername service.example.com -alpn h2,http/1.1

This illustrative command offers two protocol identifiers and shows handshake information. Replace the documentation hostname with the verified target you are authorized to test. Check the selected ALPN result and certificate verification outcome as different fields.

Do not treat s_client as a complete HTTP/2 application test. It can inspect a negotiation without exercising the normal client's requests, streaming behavior, or error handling. Also confirm that the installed diagnostic tool supports the options you use.

Never disable certificate verification in the application to make a protocol experiment pass. Trust failures and protocol negotiation failures have different causes. Fix the relevant boundary rather than weakening transport protection.

Compare the client's offer and the server's selection

If a tool offers only HTTP/1.1, a server cannot select HTTP/2 from that offer. Inspect the client's build capabilities and configuration before changing the server. Conversely, a client offer containing h2 does not prove that the endpoint enabled it.

Run matched tests from the intended client environment. A laptop browser, containerized command-line client, and legacy integration may have different support. Label each result with the exact version and route so the comparison remains interpretable.

Keep a small table: client, offered protocols where observable, selected protocol, endpoint, and result. Do not fill unobserved fields with guesses. An unknown offer is a reason for a more focused trace, not permission to infer it from a successful response.

Inspect the proxy-to-origin leg independently

If the user-facing connection uses HTTP/2 but origin logs show HTTP/1.1, that may be the intended proxy configuration. Decide whether the backend protocol affects the actual requirement. A protocol mismatch between two separate legs is not automatically evidence of failure.

Test application behavior across the deployed path, especially if the service depends on features or streaming characteristics that differ between configurations. Measure the symptom rather than assuming a protocol label alone explains latency or connection reuse.

Our HTTP connection-reuse guide discusses a related client behavior. Reusing connections and negotiating an application protocol are separate checks; neither should stand in for observing the other.

Retest after one targeted change

Change the configuration at the boundary supported by the evidence, then repeat the same client and request. Record the before-and-after selection and verify normal application responses. A handshake improvement that breaks health checks or legacy clients needs a broader rollout decision.

Keep a recovery path and monitor protocol errors during a bounded deployment. Avoid changing edge, proxy, and application settings simultaneously unless the coordinated change plan specifically requires it; otherwise the result becomes difficult to attribute.

Conclusion

Diagnose missing HTTP/2 by tracing ALPN and TLS boundaries, not by treating HTTPS as proof of a protocol. Match the hostname and client, verify each relevant connection leg, and test the actual application after a targeted configuration change.

Advertisement
HTTP/2 Missing? Check TLS ALPN Negotiation | Duck Cloud