Skip to content

feat(global-frontend): fail over when a pool frontend can't be reached - #17552

Draft
jthomson04 wants to merge 3 commits into
mainfrom
jthomson04/global-frontend-failover
Draft

jthomson04 wants to merge 3 commits into
mainfrom
jthomson04/global-frontend-failover

Conversation

@jthomson04

@jthomson04 jthomson04 commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Overview

When the Global Frontend's send to a pool frontend fails before the pool has the request, the request now goes to one other pool instead of returning 503. A request is never sent again once a pool may be running it.

On a four-region live run of the Global Frontend, the only two client errors were 503s where the send to one region's pool frontend failed and another pool could have served the request. Those runs logged only "error sending request"; #17524 now logs the cause, so the next one shows whether this retry covers it.

Stacked on #17525 (/metrics). This PR's base is that branch; it will be retargeted once #17525 merges.

Key Changes

About 15 core lines in proxy.rs; no new flags.

  • Unsent check: the request body sits in a slot that the upload stream takes on its first poll. If the send then fails and the bytes are still there, the pool never got the body, so the request goes to the selector's choice among the other pools. The body is still freed once written to the pool.
  • One retry: a request makes at most two sends. Under affinity, the session's pin moves to wherever the request lands.
  • Metrics: each send counts at its own pool in dynamo_global_frontend_requests_total, so a send that failed over shows as no_response at the first pool.
Failure Before Now
Connection refused or timed out, failed name lookup 503 One other pool tries it
Connection lost after the body was handed over 503 503; not retried, since the pool may be running the request
Pool answers with any status, or fails mid-stream Passed through Unchanged

Per request when nothing fails: one small allocation for the body slot and a copy of the header map. Nothing runs per token.

Validation

Behaviour Test
A closed pool fails over to the other pool, both pools' in-flight counts return to 0, and each send counts at its own pool in /metrics a_request_goes_to_another_pool_when_its_pool_cannot_be_reached
A pool that read the whole body and then dropped the connection is not followed by a second send; the other pool sees no request a_request_the_pool_may_have_is_not_sent_again
A single unreachable pool still gives 503 and counts no_response unreachable_pools_are_unavailable

The forwarding tests ran 15 times in a row without a failure. No live run: the change acts only when a pool frontend can't be reached.

Issues and Ongoing Work

Pull Request Checklist
  • I used Dynamo's /pr-checklist skill.

🤖 Generated with Claude Code

@jthomson04

Copy link
Copy Markdown
Contributor Author

/ok to test c08c52b

@github-actions github-actions Bot added feat documentation Improvements or additions to documentation labels Oct 28, 2026
@jthomson04
jthomson04 force-pushed the jthomson04/global-frontend-failover branch from c08c52b to e31cffd Compare October 29, 2026 00:09
@jthomson04

Copy link
Copy Markdown
Contributor Author

/ok to test e31cffd

@devin-ai-integration

devin-ai-integration Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

✅ Dynamo PR CI passed — run 40931437125 (attempt 1) on 070debde93

Gate checks: ✅ backend-status-check · ✅ deploy-status-check · ✅ dynamo-status-check

Posted automatically by Devin for run 40931437125. Updated on every full-CI run of this PR.

@jthomson04

Copy link
Copy Markdown
Contributor Author

/ok to test 98fe133

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

@jthomson04
jthomson04 force-pushed the jthomson04/global-frontend-passthrough branch from f088c63 to 7c924bc Compare October 29, 2026 05:17
@jthomson04
jthomson04 force-pushed the jthomson04/global-frontend-failover branch from 98fe133 to c09fdfa Compare October 29, 2026 05:17
@jthomson04

Copy link
Copy Markdown
Contributor Author

/ok to test c09fdfa

Serve the Global Frontend's own Prometheus families,
dynamo_global_frontend_*: requests per pool by response status (with a
local label for the in-region share, and cancelled for a client that
leaves before the pool answers), requests answered without a pool, time
to first byte and duration per pool, responses that broke off, and
requests in flight per pool.

Series are labelled with the pool's name and region, never with the
request's model. Pools now carry a name for people, their
<cluster>/<namespace>/<DGD name>. Inter-token latency and token counts
need the stream parsed and stay with the pool frontends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
@jthomson04
jthomson04 force-pushed the jthomson04/global-frontend-passthrough branch from 7c924bc to eb4f370 Compare October 29, 2026 16:57
@jthomson04

Copy link
Copy Markdown
Contributor Author

/ok to test 298196c

@jthomson04
jthomson04 force-pushed the jthomson04/global-frontend-failover branch from c09fdfa to 298196c Compare October 29, 2026 17:44
jthomson04 and others added 2 commits October 29, 2026 11:28
A Dynamo pool frontend sends its response headers once a worker has the
request, so a client that gives up while a worker queues its request counts
under the pool's status, not as cancelled. Also note that an SSE keep-alive
before the first token counts as the first byte, and list no_response in the
README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
A send to a pool frontend that fails before the pool has the request body
(connection refused or timed out, or a failed name lookup) now goes to one
other pool instead of returning 503. The body sits in a slot the upload
stream takes on its first poll, so it is still freed once written; a send
that fails after the pool took it is not retried, since the pool may be
running the request. Each send counts at its own pool in /metrics.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
@jthomson04

Copy link
Copy Markdown
Contributor Author

/ok to test 070debd

@jthomson04
jthomson04 force-pushed the jthomson04/global-frontend-failover branch from 298196c to 070debd Compare October 29, 2026 18:30
Base automatically changed from jthomson04/global-frontend-passthrough to main October 29, 2026 19:45

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

documentation Improvements or additions to documentation feat size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant