[GH-ISSUE #438] Fetch cache stale-while-revalidate refetch not registered with waitUntil() #95

Closed
opened 2026-05-06 12:37:11 +02:00 by BreizhHardware · 0 comments

Originally created by @Divkix on GitHub (Mar 11, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/438

Bug

When the fetch cache returns a stale entry, it fires a background refetch to refresh the cache. This refetch is fire-and-forget — the promise is not registered with ExecutionContext.waitUntil().

On Cloudflare Workers, once the Response is sent, the isolate terminates and kills the in-flight refetch. Stale entries never get refreshed.

Expected behavior

The background refetch promise should be registered with waitUntil() so the Workers runtime keeps the isolate alive until the refetch completes, matching the pattern already used by ISR in isr-cache.ts.

Reproduction

  1. Deploy an app to Cloudflare Workers with fetch caching enabled (next: { revalidate: N })
  2. Make a request that populates the fetch cache
  3. Wait for the TTL to expire
  4. Make another request — stale data is returned, background refetch fires
  5. The isolate terminates before the refetch completes
  6. Subsequent requests continue returning stale data indefinitely

Relevant code

  • packages/vinext/src/shims/fetch-cache.ts lines 583-617 — fire-and-forget refetch
  • packages/vinext/src/shims/isr-cache.ts lines 110-111 — correct pattern using getRequestExecutionContext()?.waitUntil()
Originally created by @Divkix on GitHub (Mar 11, 2026). Original GitHub issue: https://github.com/cloudflare/vinext/issues/438 ## Bug When the fetch cache returns a stale entry, it fires a background refetch to refresh the cache. This refetch is fire-and-forget — the promise is **not** registered with `ExecutionContext.waitUntil()`. On Cloudflare Workers, once the Response is sent, the isolate terminates and kills the in-flight refetch. **Stale entries never get refreshed.** ## Expected behavior The background refetch promise should be registered with `waitUntil()` so the Workers runtime keeps the isolate alive until the refetch completes, matching the pattern already used by ISR in `isr-cache.ts`. ## Reproduction 1. Deploy an app to Cloudflare Workers with fetch caching enabled (`next: { revalidate: N }`) 2. Make a request that populates the fetch cache 3. Wait for the TTL to expire 4. Make another request — stale data is returned, background refetch fires 5. The isolate terminates before the refetch completes 6. Subsequent requests continue returning stale data indefinitely ## Relevant code - `packages/vinext/src/shims/fetch-cache.ts` lines 583-617 — fire-and-forget refetch - `packages/vinext/src/shims/isr-cache.ts` lines 110-111 — correct pattern using `getRequestExecutionContext()?.waitUntil()`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#95
No description provided.