[wrangler] Make startup network requests non-blocking on slow connections#13386
Merged
petebacondarwin merged 7 commits intocloudflare:mainfrom Apr 13, 2026
Merged
Conversation
Make startup network requests non-blocking on slow/degraded connections (airplane wifi, trains) by applying the industry-standard two-tier pattern: non-critical requests are bounded, not awaited indefinitely. - update-check: Race against 100ms grace period in banner (cache hit resolves in <1ms via I/O poll). 3s safety-net timeout caps the library's auth-retry path. New WRANGLER_UPDATE_CHECK=false env var to disable. - cf.json fetch: AbortSignal.timeout(3000) with existing fallback to hardcoded Austin, TX data. - metrics dispatch: Remove unnecessary AbortSignal.timeout — exit handler's 1s race already covers shutdown. Closes cloudflare#9946 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 4a331c2 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
|
Codeowners approval required for this PR:
Show detailed file reviewers |
petebacondarwin
requested changes
Apr 10, 2026
Contributor
petebacondarwin
left a comment
There was a problem hiding this comment.
Let's remove the env var. Otherwise LGTM
create-cloudflare
@cloudflare/kv-asset-handler
miniflare
@cloudflare/pages-shared
@cloudflare/unenv-preset
@cloudflare/vite-plugin
@cloudflare/vitest-pool-workers
@cloudflare/workers-editor-shared
wrangler
commit: |
Addresses @petebacondarwin's review feedback — removes the WRANGLER_UPDATE_CHECK=false env var. The timeout-based approach is sufficient without an additional kill switch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
Author
|
@petebacondarwin Removed the |
petebacondarwin
approved these changes
Apr 13, 2026
petebacondarwin
approved these changes
Apr 13, 2026
workers-devprod
approved these changes
Apr 13, 2026
Contributor
workers-devprod
left a comment
There was a problem hiding this comment.
Codeowners reviews satisfied
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
Author
|
@petebacondarwin Fixed the |
Merged
petebacondarwin
pushed a commit
that referenced
this pull request
Apr 14, 2026
…ions (#13386) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #9946.
Problem
Wrangler makes network requests during startup (npm update check,
request.cfdata fetch, telemetry dispatch) that block the CLI indefinitely on slow or degraded connections. Users report 10+ second delays on airplane wifi and trains, with no spinner, timeout, or way to disable.Confirmed by @penalosa and @threepointone in the issue thread. Latest comment (@kalcodes, 2026-04-09) reports "failures never exit" when offline.
Root Cause
Three network calls with zero timeout:
update-check.ts→await checkForUpdate()request.cffetchminiflare/src/cf.ts→await fetch(cf.json)metrics-dispatcher.ts→ fire-and-forgetSolution
Applies the industry-standard two-tier pattern (same approach as npm's
update-notifier, yarn, pnpm): non-critical startup requests are bounded, not awaited indefinitely.Change 1: Update check — non-blocking banner with grace period (
update-check.ts,wrangler-banner.ts)Before:
await updateCheck()in the banner blocks indefinitely until npm registry responds.After: The banner races the update check against a 100ms grace period:
Why 100ms? The
update-checklibrary caches results in/tmp/update-check/. On a cache hit (>99% of runs), thereadFileI/O completes in <1ms — theawaityields, the event loop reaches the I/O poll phase, and the readFile callback fires before the 100ms timer. On a cache miss (network needed), the timer wins and the banner prints immediately.Evidence — Node.js event loop ordering proves correctness:
await Promise.race(...)yields → microtask queue drains/tmpcallback fires (~0.5ms)evaluateCache()→checkForUpdate()→updateCheck()resolves → race settlesAdditionally, a 3s safety-net timeout (
UPDATE_CHECK_TIMEOUT_MS) is added insidedoUpdateCheck()viaPromise.race. This caps theupdate-checklibrary's auth-retry path — the library has a 2s socket timeout, but retries with auth on 4xx, potentially doubling to 4s. The.unref()on the timer prevents process exit delay.New env var:
WRANGLER_UPDATE_CHECK=falsedisables the update check entirely.Change 2:
request.cffetch — AbortSignal timeout (miniflare/src/cf.ts)On timeout, the existing
catchblock returnsfallbackCf(hardcoded Austin, TX data).AbortSignal.timeoutis already used 10+ times in the codebase — established pattern.Change 3: Metrics dispatch — remove dead code (
metrics-dispatcher.ts)The telemetry fetch is fire-and-forget. The exit handler in
index.ts:2265-2268already racesallMetricsDispatchesCompleted()against a 1s timeout:An
AbortSignal.timeout(3000)on the fetch would never fire in practice because the 1s exit timeout always wins first. During long-running commands (wrangler dev), the dangling connection doesn't block anything. Removed the dead timeout, updated the comment to document why.Verification Evidence
6 independent verification agents were run in parallel, each examining a different aspect:
Type checking:
pnpm run -r --filter wrangler check:typepasses with zero errors.Grill-tested design decisions
Each design choice was challenged through adversarial review:
main()printBanner: falsecommands (build, kv, tail)WRANGLER_UPDATE_CHECKonly acceptsfalse0/nowork too?true/false)signaloption. The changes only affect timeout behavior on slow/degraded real networks, which cannot be reliably unit tested.WRANGLER_UPDATE_CHECKenv var is a power-user escape hatch. Changeset describes user-facing changes for the changelog.🤖 Generated with Claude Code