Skip to content

Add an opt-in HTTP/2 connection soft limit - #924

Draft
thliu21 wants to merge 1 commit into
swift-server:mainfrom
thliu21:feature/http2-connection-soft-limit-567
Draft

thliu21 wants to merge 1 commit into
swift-server:mainfrom
thliu21:feature/http2-connection-soft-limit-567

Conversation

@thliu21

@thliu21 thliu21 commented Sep 10, 2026

Copy link
Copy Markdown

HTTP/2 requests currently queue behind the server's MAX_CONCURRENT_STREAMS limit even when the server could handle more connections. This adds ConnectionPool.concurrentHTTP2ConnectionsPerHostSoftLimit for #567, defaulting to 1. With a server limit of one stream and a connection limit of two, two requests can run concurrently while a third remains queued.

This is a draft for API and behavior alignment.

Proposed behavior

  • Reuse available streams, then expand on queued demand, waiting for a relevant pending connection attempt before expanding further.
  • Count active, starting, and backing-off connections toward the soft limit; exclude draining connections.
  • Allow a required event loop to exceed the limit to establish its first usable connection. Preserve the default's existing protocol-migration exception of one connection per event loop.
  • Reevaluate queued demand after SETTINGS, retries, GOAWAY, protocol migration, and connection closure, including capacity released on another event loop.

The setting is also available through Swift Configuration. This proposal expands only after server-advertised stream capacity is exhausted; distributing requests across more connections before saturation is outside this patch.

Validation

On macOS with Swift 6.3.2:

  • swift test -j 4 --filter 'HTTPConnectionPool|HTTP2|SwiftConfiguration': 167 XCTest + 32 Swift Testing configuration tests passed.
  • Includes 15 deterministic state-machine regressions and a localhost TLS/HTTP2 test that verifies the public configuration opens two connections when each permits one stream.
  • Regression tests were observed failing before the corresponding changes. Strict formatting and git diff --check passed.

Linux/minimum-toolchain validation, the full package suite, and throughput/latency benchmarks have not been run. The localhost test establishes concurrent capacity, not a measured performance improvement.

Does the default, required-event-loop exception, and demand-driven growth policy match the intended scope of #567?

Motivation:

A single HTTP/2 connection queues requests after the server's concurrent
stream limit is reached. Issue swift-server#567 asks for configurable connection
capacity so those requests can use another connection.

Modifications:

Add concurrentHTTP2ConnectionsPerHostSoftLimit, defaulting to 1, and expose
it through Swift Configuration. Expand on queued demand while respecting
pending attempts, stream availability, and required event-loop coverage.
Handle retries, SETTINGS, GOAWAY, protocol migration, and capacity released
on other event loops. Cover the policy with deterministic state-machine
regressions and a localhost TLS/HTTP2 test using one stream per connection.

Result:

Opt-in clients can use multiple HTTP/2 connections after available streams
are exhausted, while the default retains existing migration behavior.
The affected macOS suites pass 167 XCTest and 32 configuration tests;
format and whitespace checks pass. Maintainer agreement on the proposed
API and Linux validation remain pending.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant