Skip to content

[Experimental] Implement option to opt out of revalidation after setting or deleting a cookie in a Server Action - #98058

Open
brunorodmoreira wants to merge 1 commit into
vercel:canaryfrom
brunorodmoreira:feat/cookie-mutation-revalidate-opt-out
Open

[Experimental] Implement option to opt out of revalidation after setting or deleting a cookie in a Server Action#98058
brunorodmoreira wants to merge 1 commit into
vercel:canaryfrom
brunorodmoreira:feat/cookie-mutation-revalidate-opt-out

Conversation

@brunorodmoreira

@brunorodmoreira brunorodmoreira commented Aug 28, 2026

Copy link
Copy Markdown

Reworks #84313 by @cramforce. That PR has been open since September 2025, now conflicts with canary after the recent action refactors, and hasn't had maintainer movement despite people asking for news on it through 2026 (better-auth among them). I opened this as a fresh PR so the feature can be tracked and reviewed against current canary. Happy to close this one if the original gets picked up instead.

What?

Adds an experimental revalidate?: boolean option to cookies().set() and cookies().delete(), on both call forms. Passing { revalidate: false } opts that mutation out of marking the path as revalidated.

When a mutation opts out, the action response skips the page re-render and the x-action-revalidated header is not sent, so client router caches stay intact. The cookie still reaches the browser through Set-Cookie as usual.

Why?

Original report: https://x.com/madarco/status/1972314852036374833

better-auth/better-auth#9363 names the option from #84313 as the root fix for their session cookie workaround. Their idempotency check can't handle cookie values that carry a timestamp, so every refresh triggers a full re-render.

There is no workaround today. The re-render is embedded in the action response on the server, so it can't be avoided with a proxy or by stripping headers on the way out.

How?

All of the option handling lives in the inner MutableRequestCookiesAdapter.wrap proxy. It strips revalidate before the option can reach the cookie store, sets pathWasRevalidated conditionally, and keeps a monotonic latch (Symbol.for('next.mutated.cookies.revalidate')) recording whether any mutation in the request asked for revalidation.

addRevalidationHeader in action-handler.ts now consults that latch instead of getModifiedCookieValues().length. This resolves madarco's review comment on the original PR: without it, the client is still told to revalidate.

What's different from #84313:

  • delete() is supported in both call forms (madarco's other review comment).
  • The unused option extraction vercel[bot] flagged in createCookiesWithMutableAccessCheck is resolved by forwarding the option untouched into the inner proxy.
  • Rebased onto the ActionRevalidationKind refactor (Fix: Server refresh() should not purge client cache #86878). An opt-out never downgrades revalidation coming from refresh() or revalidatePath().

Opted-out cookies stay in the modified cookies list, so route handlers, redirects, and middleware Set-Cookie emission are unchanged.

Known limitation, documented in the JSDoc: cookies set in middleware and merged into the action always revalidate.

…kie mutations in Server 操作

Setting or deleting a cookie in a Server Action marks the path as
revalidated, which re-renders the page into the action response and
invalidates the client router caches. For mutations that don't affect
rendered content (e.g. refreshing a session cookie), this is wasted work.

cookies().set() and cookies().delete() now accept an experimental
revalidate option; { revalidate: false } opts the mutation out:

- MutableRequestCookiesAdapter strips the option before it reaches the
  underlying cookie store, skips the pathWasRevalidated marking, and
  tracks whether any mutation requested revalidation (a monotonic latch
  exposed via Symbol.for('next.mutated.cookies.revalidate')).
- addRevalidationHeader consults that latch instead of counting modified
  cookies, so the x-action-revalidated header is not sent when all
  mutations opted out. Opted-out cookies are still recorded as modified
  and emitted via Set-Cookie, route handler responses, and redirects.
- Reworks vercel#84313 and addresses its review feedback: delete() support,
  the action-handler cookie check, and the unused option extraction in
  createCookiesWithMutableAccessCheck (the option is now handled by the
  inner adapter proxy that userspace cookies forward into).
注册 for free to join this conversation on GitHub. Already have an account? 登录 to comment

标签

None yet

项目

None yet

Development

Successfully merging this pull request may close these issues.

1 participant