@@ -178,59 +178,8 @@ const mcpAgentHandler = makeCloudMcpAgentHandler({
178178 traceRequest : traceCloudMcpRequest ,
179179} ) ;
180180
181- // ---------------------------------------------------------------------------
182- // Start server-graph warmup
183- // ---------------------------------------------------------------------------
184- //
185- // Page latency was p50 19-49ms every day up to 2026-08-16 and 2728ms the day
186- // after the 21:20 UTC deploy. It is not load: 2026-08-11 served MORE total
187- // traffic (5.43M requests vs 4.38M) with pages at p50 41ms, so the
188- // reconnect-storm/volume explanation does not hold.
189- //
190- // What changed is where MCP work runs. The old hibernatable Agent bridge
191- // handed `/mcp` to the Durable Object almost immediately; the v2 stack
192- // authenticates and dispatches in the WORKER (`mcp.auth.jwt_verify` alone runs
193- // ~35k times per 6h there). That spins up far more worker isolates, and `/mcp`
194- // returns above without ever touching `fetchHandler` — so those isolates never
195- // load the Start graph. Page requests then land on them cold and pay
196- // `loadEntries`: measured p50 **3.1s**, against p50 33ms for the request's own
197- // work and 9-104ms for a warm isolate. The same bundle in local workerd serves
198- // the same path in ~3ms, so this is a cold-isolate cost, not slow code.
199- //
200- // So warm on the isolate's FIRST fetch, in the background: MCP traffic then
201- // pre-warms an isolate before a page request reaches it. This is #1628, which
202- // worked; it was reverted (#1634) when memory-limit kills jumped, but that
203- // landed during the 2026-08-17 storm — 11.67M requests in a day against a
204- // 2.6-4.3M baseline. Volume is back to baseline and `exceededMemory` is
205- // currently zero, so the condition that made it expensive is gone.
206- // `START_GRAPH_WARM=false` disables it without a deploy.
207- //
208- // Deliberately NOT at module scope: a full warmup there trips workerd's
209- // global-scope I/O restriction, and DO-only isolates should not carry the SSR
210- // graph.
211- // ---------------------------------------------------------------------------
212-
213- let startGraphWarmupStarted = false ;
214-
215- const warmStartGraph = ( env : Env ) : void => {
216- if ( startGraphWarmupStarted ) return ;
217- if ( env . START_GRAPH_WARM === "false" ) return ;
218- startGraphWarmupStarted = true ;
219- // oxlint-disable-next-line executor/no-promise-catch -- adapter boundary; fire-and-forget warmup outside any Effect runtime
220- void Promise . all ( [ import ( "#tanstack-router-entry" ) , import ( "#tanstack-start-entry" ) ] ) . catch (
221- ( ) => {
222- // Advisory only — the request path still loads the graph lazily.
223- startGraphWarmupStarted = false ;
224- } ,
225- ) ;
226- } ;
227-
228181const cloudflareHandler : ExportedHandler < Env > = {
229182 fetch : async ( request , env , ctx ) => {
230- // First fetch in this isolate kicks the graph load off in the background,
231- // including for /mcp — MCP traffic is what reaches these isolates first.
232- warmStartGraph ( env ) ;
233-
234183 // Public pages must not enter TanStack Start: its first-request dynamic
235184 // import loads the entire React + Effect server graph and can take seconds
236185 // on a cold isolate. Classify and service-bind marketing at the Worker
0 commit comments