Skip to content

Add HTTP/2 keepalive options to ConnectionOptions#430

Merged
yoshidan merged 1 commit intoyoshidan:mainfrom
h-michael:add-http2-keepalive-options
Mar 18, 2026
Merged

Add HTTP/2 keepalive options to ConnectionOptions#430
yoshidan merged 1 commit intoyoshidan:mainfrom
h-michael:add-http2-keepalive-options

Conversation

@h-michael
Copy link
Copy Markdown
Contributor

Summary

  • Add http2_keep_alive_interval, keep_alive_timeout, and keep_alive_while_idle fields to ConnectionOptions in gax, mapped to tonic Endpoint methods
  • Expose these options through each gRPC service crate's config structs (spanner ChannelConfig, spanner admin AdminClientConfig, bigquery ChannelConfig, artifact-registry ClientConfig)
  • pubsub and kms already expose ConnectionOptions directly, so no additional changes needed

Motivation

Without HTTP/2 keepalive, when an intermediate network device (load balancer, NAT, etc.) silently drops a connection, the client cannot detect the dead connection until the TCP retransmission timeout (~13-30
minutes depending on OS settings). This is particularly problematic for long-lived streaming RPCs like Pub/Sub streaming pull.

HTTP/2 PING frames allow the client to detect dead connections within interval + timeout (e.g., 50 seconds with 30s interval + 20s timeout) instead of waiting for TCP-level timeouts.

Google's official Go client configures HTTP/2 keepalive for this reason. tonic 0.14 already supports these settings on Endpoint without additional feature flags.

All defaults are None (keepalive disabled), so this is a non-breaking behavioral change. Users opt in by setting the fields explicitly.

Note: adding new fields to ConnectionOptions and other config structs is a source-breaking change for users who construct them with struct literals without ..Default::default().

Example

let config = ClientConfig {
    connection_option: ConnectionOptions {
        http2_keep_alive_interval: Some(Duration::from_secs(30)),
        keep_alive_timeout: Some(Duration::from_secs(20)),
        keep_alive_while_idle: Some(true),
        ..Default::default()
    },
    ..Default::default()
};

Note

@yoshidan
All new keepalive fields default to None (keepalive disabled) to preserve backward compatibility. An alternative would be to set sensible defaults (e.g., 30s interval, 20s timeout, idle=true) out of the box, which would benefit all users without requiring explicit configuration. Happy to change this if you prefer enabling keepalive by default.

Related issues

Add http2_keep_alive_interval, keep_alive_timeout, and
keep_alive_while_idle fields to ConnectionOptions in gax,
and expose them through each gRPC service crate's config
structs so users can configure HTTP/2 PING-based keepalive
to detect dead connections promptly.
@yoshidan yoshidan added the safe to test safe to test label Mar 17, 2026
@yoshidan
Copy link
Copy Markdown
Owner

LGTM.
We will initially release the update without changing the default values ​​to maintain backward compatibility.
Default values ​​may vary depending on the component.

@yoshidan yoshidan merged commit 34d4508 into yoshidan:main Mar 18, 2026
9 checks passed
@h-michael h-michael deleted the add-http2-keepalive-options branch March 18, 2026 02:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test safe to test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants