Skip to content

Add graceful HTTP/2 connection draining via max_connection_age#364

Open
procmarchal wants to merge 2 commits intosneako:mainfrom
procmarchal:main
Open

Add graceful HTTP/2 connection draining via max_connection_age#364
procmarchal wants to merge 2 commits intosneako:mainfrom
procmarchal:main

Conversation

@procmarchal
Copy link
Copy Markdown

Add graceful HTTP/2 connection draining via max_connection_age

Fixes #363

Approach

Introduces two new http2: pool options — max_connection_age and max_connection_age_jitter — that let Finch proactively recycle HTTP/2 connections after a configured lifetime. This enables client-side load balancing against Kubernetes headless services, where long-lived HTTP/2 connections would otherwise stay pinned to a single pod.

When the age timer fires the pool unregisters itself from the Registry (so new requests are immediately routed elsewhere), finishes any in-flight requests in :connected_read_only, then terminates normally. The supervisor restarts it with a fresh DNS lookup. Requests that land on a draining pool via request/3, stream/5, or stream_while/5 are transparently retried (up to 3 times); async_request/3 callers receive the :read_only error and must retry manually (documented in the @doc).

Add graceful HTTP/2 connection draining via max_connection_age

Introduces two new `http2:` pool options — `max_connection_age` and
`max_connection_age_jitter` — that let Finch proactively recycle HTTP/2
connections after a configured lifetime. This enables client-side load
balancing against Kubernetes headless services, where long-lived HTTP/2
connections would otherwise stay pinned to a single pod.

When the age timer fires the pool unregisters itself from the Registry
(so new requests are immediately routed elsewhere), finishes any
in-flight requests in `:connected_read_only`, then terminates normally.
The supervisor restarts it with a fresh DNS lookup. Requests that land
on a draining pool via `request/3`, `stream/5`, or `stream_while/5` are
transparently retried (up to 3 times); `async_request/3` callers receive
the `:read_only` error and must retry manually (documented in the @doc).

Made-with: Cursor
@procmarchal procmarchal changed the title Add graceful HTTP/2 connection draining via max_connection_age (#1) Add graceful HTTP/2 connection draining via max_connection_age Apr 6, 2026
Copy link
Copy Markdown
Collaborator

@NelsonVides NelsonVides left a comment

Choose a reason for hiding this comment

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

All right! My first thought was that this is not a feature I'd use and therefore performance-wise didn't want to pay the price for it. But then I checked the code and well, I don't think there'd be any relevant performance penalty, the implementation is very clean! Then I thought well, wait, maybe actually I do have a use case for this. Then I read the code again and thought: thank you!

Ok, first thing, could you rebase on top of the latest master and resolve conflicts? 🙏🏽

@procmarchal procmarchal requested a review from NelsonVides April 15, 2026 07:53
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.

[Feature] Add HTTP/2 connection max-age draining for client-side load balancing

2 participants