Skip to content

feat(spanner): add experimental numChannels round-robin transport mode#8138

Open
rahul2393 wants to merge 8 commits intomainfrom
fix-channel-affinity
Open

feat(spanner): add experimental numChannels round-robin transport mode#8138
rahul2393 wants to merge 8 commits intomainfrom
fix-channel-affinity

Conversation

@rahul2393
Copy link
Copy Markdown
Contributor

@rahul2393 rahul2393 commented Apr 30, 2026

Summary

Adds an experimental fixed-channel round-robin mode for Spanner data RPCs.

By default, when no customer grpc.gcpApiConfig is provided, Spanner now uses numChannels = 4 and disables grpc-gcp channel pooling for Spanner data RPCs. Customers can override the channel count with numChannels, or continue using grpc-gcp by passing a custom grpc.gcpApiConfig.

When fixed-channel mode is active:

  • grpc-gcp call transformer/channel factory config is disabled
  • grpc.use_local_subchannel_pool = 1 is set so grpc-js does not share one transport
  • Spanner data clients are keyed by channel index
  • non-transactional Spanner RPCs use round-robin channel selection
  • transaction RPCs keep a per-transaction channel hint so begin/read/query/commit/rollback stay on the same channel

Motivation

Multiplexed sessions currently bind transaction RPCs to the session affinity key under grpc-gcp, which can pin high-concurrency write workloads to one HTTP/2 transport. Fixed-channel mode enables round-robin distribution while preserving transaction stickiness.

Validation

Added local benchmark tooling with Go mock Spanner server:

  • 110 concurrent table.insert() calls
  • 50ms injected Commit latency
  • mux session default

Observed warmed run with default numChannels = 4:

  • P50: ~94.65ms
  • P90: ~94.99ms
  • P99: ~95.17ms
  • 4 server-side transports
  • Commit distribution: 27/27/28/28
  • 110/110 transaction affinity hits
  • 0 affinity misses

Observed warmed run with SPANNER_NUM_CHANNELS=10:

  • P50: ~90.60ms
  • P90: ~91.08ms
  • P99: ~91.61ms
  • 10 server-side transports
  • 11 Commit RPCs per transport
  • 110/110 transaction affinity hits
  • 0 affinity misses

Notes

This is experimental and currently focused on Spanner data RPC routing. Admin clients continue to use normal shared client behavior. Customers with custom grpc-gcp configs can keep the grpc-gcp path by passing grpc.gcpApiConfig.

@rahul2393 rahul2393 requested a review from a team as a code owner April 30, 2026 06:12
@product-auto-label product-auto-label Bot added the api: spanner Issues related to the Spanner API. label Apr 30, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an experimental numChannels option to the Spanner client, enabling manual gRPC channel pooling and round-robin assignment for transaction RPCs as an alternative to grpc-gcp. The changes involve managing multiple internal client instances within the Spanner class and ensuring that transactions consistently use the same channel via a channelHint. Feedback was provided regarding the round-robin counter implementation to avoid potential precision loss by applying the modulo operation during increment.

Comment thread handwritten/spanner/src/index.ts Outdated
@rahul2393 rahul2393 force-pushed the fix-channel-affinity branch from d2b0789 to 16ef557 Compare April 30, 2026 07:25
@rahul2393 rahul2393 force-pushed the fix-channel-affinity branch from db605e3 to 77dea0d Compare April 30, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: spanner Issues related to the Spanner API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant