Remix serverless adapters not applying expected Cache‑Control headers on GET loader responses
0 reputation · 20 Feb 2025, 19:04 UTC
0 reputation · 20 Feb 2025, 19:04 UTC
Determine whether Remix automatically adds a Cache‑Control header to GET loader responses when deployed via a serverless adapter, or whether developers must explicitly return the header from the loader.
The Vercel and Netlify adapters honor the headers function returned from loaders, but the Cloudflare Workers adapter strips unknown headers unless they are listed in the wrangler.toml compatibility flags, leaving it unclear if Remix supplies any default headers for low‑traffic workloads.
Does Remix inject a default Cache‑Control header for GET loader responses with the Vercel adapter? Is manual header setting required for the Cloudflare Workers adapter to preserve Cache‑Control? Are there adapter‑specific configuration flags that enable automatic header injection?
29775 reputation · 20 Feb 2025, 19:39 UTC
Remix does not inject a default Cache-Control header on GET loader responses — not on Vercel, not anywhere else. If you want caching, you must return the header yourself, either from the loader or from the route's headers export. There are no adapter-specific flags in Remix that turn on automatic header injection. Caching is an explicit, per-route decision by design, because Remix can't know whether your data is public, per-user, or time-sensitive.
return json(data, { headers: { 'Cache-Control': 'public, max-age=60' } }).headers export, it controls the final document headers. It receives loaderHeaders and must forward them — defining headers() without merging loaderHeaders silently drops the loader's Cache-Control. This is the most common cause of "my header disappeared."throw json(...), throw redirect(...)) do not inherit success-path headers; set headers on the thrown Response itself./build files) is configured separately at the host/CDN layer and is unrelated to loader response caching.Separating what's Remix's fault from what's the platform's:
vercel.json for a headers rule overriding the route, and check whether the response sets Set-Cookie (session access often causes platforms to rewrite Cache-Control to private/no-store).wrangler.toml compatibility flags does not match established Workers behavior — compatibility flags gate runtime API features, not response header allowlists. Flag this premise for review. More likely causes are the headers export dropping loaderHeaders, or a Worker/Pages Functions layer or Cache API config modifying the response after Remix returns it.json() in favor of returning raw Response objects. Verify against your installed version.Run the same app locally with the Express adapter and compare against production:
curl -si https://your-app.example.com/route | grep -i cache-control
curl -si http://localhost:3000/route | grep -i cache-controlIf local is correct and production is wrong, the platform edge is rewriting headers — Remix is not involved. If both are wrong, inspect the route: does a headers export exist, and does it return loaderHeaders (or merge them) rather than replacing them? Also test the loader without touching the session to rule out Set-Cookie-triggered rewriting.
Before adding public caching, confirm the response doesn't vary per user. If it depends on cookies or auth, use private or add Vary: Cookie — otherwise a shared CDN cache can serve one user's data to another.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.