Files

Workers Response Store adapter POC

This example uses one responseStoreAdapter() from @vinext/cloudflare in place of both cdnAdapter() and kvDataAdapter(). The application Worker keeps Workers Cache disabled. Its RESPONSE_STORE service binding calls a separately deployed cache Worker that owns Workers Cache, R2 response bodies, SQLite Durable Object metadata, tag indexes, and SWR regeneration.

The cache Worker is shared infrastructure, not a second deployment of the application. Each application version has one ordinary build and deploy. Cached entries retain a loopback to that application version's vinext response-stage entrypoint. Route and fetch-cache entries can replay that stage, while a transformed public "use cache" entry records its encrypted arguments and server-reference identity so regeneration invokes only that function. If its arguments cannot be safely recorded, the adapter falls back to replaying the cacheable route.

On a page or RSC miss, vinext streams the render to the visitor while an independent bounded branch runs completed-response admission. A clean, cacheable response is inserted into Response Store in the background; late dynamic usage, timeout, or size rejection prevents publication without delaying the foreground response, while a source stream failure terminates both branches. The initial MISS status describes the lookup result because final admission happens after its headers have been sent. Route Handlers retain their completion barrier so body-time cookie, draft-mode, and cache-tag changes are reflected before headers are finalized. Warmup and loopback regeneration still wait for admission and durable publication because those operations must not report success before the replacement exists. Cache headers never enable Workers Cache on the application Worker; they only carry the admitted response policy to the cache Worker.

During SWR, Workers Cache returns its stale response immediately and invokes the cache Worker in the background. The cache Worker cannot currently distinguish that update from an empty edge location reading stale R2 data, so it returns the stale R2 response immediately instead of risking a blocking read. It regenerates through the application loopback, replaces the R2 revision only after vinext completed-response admission confirms the result is cacheable, and allows a later Workers Cache request to promote it. This can produce one extra stale response until the invocation reason is available to the cache Worker.

Automatic loopback regeneration is attached only to replay-safe GET and HEAD renders. Data written during actions or other non-replayable requests remains available and can still be invalidated explicitly, but Response Store will not replay that request in the background.

Wiring

vite.config.ts contains the complete vinext integration:

import { responseStoreAdapter } from "@vinext/cloudflare/cache/response-store-adapter";

vinext({ cache: responseStoreAdapter() });

wrangler.jsonc supplies only the RESPONSE_STORE service binding and CF_VERSION_METADATA metadata binding. It does not bind KV, R2, a Durable Object, or Workers Cache to the application Worker. The adapter-generated Worker entry runs vinext's request stage, performs Response Store lookups, admits completed non-dynamic renders, and exports the loopback revalidator entrypoint.

Routes

  • /cached/[slug] exercises App Router ISR and tag/path revalidation.
  • /use-cache exercises a dynamic route whose cached function is regenerated by Response Store.
  • /use-cache-expired verifies that hard-expired data blocks on loopback regeneration.
  • /api/now exercises cached App Route responses.
  • /pages-prewarm exercises Pages Router ISR.
  • /dynamic and /vary verify that unsafe completed responses bypass shared storage.

Canonical App Router RSC requests use the same response-stage transport:

curl 'https://workers-cache.vinext.workers.dev/cached/intro.rsc?_rsc=' -H 'Accept: text/x-component' -H 'RSC: 1'

Build and deploy

Deploy the shared cache Worker only when its implementation or bindings change:

pnpm --filter @vinext/workers-response-store run build
pnpm --filter workers-cache exec wrangler deploy --config ../../packages/workers-response-store/example/service-binding/wrangler.cache.jsonc

Then build and deploy the application once:

pnpm --filter workers-cache run build
pnpm --filter workers-cache exec wrangler deploy