nextjs - ✅(Solved) Fix `useSkewCookie` sets `__vdpl` cookie on `_next/static` responses, breaking weighted deployments [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#89726Fetched 2026-04-08 02:02:26
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
0
Timeline (top)
labeled ×3closed ×1commented ×1issue_type_added ×1

Root Cause

Expected: The __vdpl cookie should only be set on responses that go through application routing (page navigations, API routes, RSC payloads) — not on _next/static responses. Static asset responses should not establish or change version affinity because:

PR fix notes

PR #78841: Add handling for setting deployment id via cookie

Description (problem / solution / changelog)

As discussed this adds a flag to allow setting deployment ID via a cookie instead of in query string on asset requests which allows for better caching with the trade-off of users potentially staying on older deployments longer until the ID is no longer accepted or the session cookie is cleared.

Changed files

  • packages/next/src/build/webpack/plugins/define-env-plugin.ts (modified, +4/-1)
  • packages/next/src/lib/load-custom-routes.ts (modified, +12/-0)
  • packages/next/src/server/config-schema.ts (modified, +1/-0)
  • packages/next/src/server/config-shared.ts (modified, +2/-0)
  • packages/next/src/server/next-server.ts (modified, +3/-1)
  • test/production/deployment-id-handling/app/next.config.js (modified, +3/-0)
  • test/production/deployment-id-handling/deployment-id-cookie-handling.test.ts (added, +79/-0)

Code Example

Next.js: 16.1.6
Deployment: Self-hosted on Kubernetes with weighted rollout strategy
Config: deploymentId: process.env.BUILD_ID, experimental.useSkewCookie: true
Output: standalone

---

headers.unshift({
-   source: '/:path*',
+   source: '/((?!_next/static).*)',
    headers: [
      {
        key: 'Set-Cookie',
        value: `__vdpl=${config.deploymentId}; Path=/; HttpOnly`,
      },
    ],
  });
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/load-custom-routes.ts#L722-L731

To Reproduce

  1. Configure next.config.js with deploymentId and experimental.useSkewCookie: true
  2. Deploy two versions simultaneously behind a load balancer with weighted traffic routing (e.g., 50/50 split)
  3. Load a page — the initial HTML response sets Set-Cookie: __vdpl={stable-sha}
  4. Observe that _next/static chunk requests also receive Set-Cookie: __vdpl={responding-pod-sha}
  5. When a chunk request is routed to the other deployment (which returns 404 — it doesn't have that build's chunks), the 404 response still sets Set-Cookie: __vdpl={other-sha}, overwriting the original cookie
  6. The client is now pinned to a deployment it wasn't assigned to

Current vs. Expected behavior

Current: useSkewCookie injects Set-Cookie: __vdpl={deploymentId} on all responses via source: '/:path*', including _next/static asset responses. In multi-deployment environments with per-request routing, this causes static asset 404s from the wrong deployment to overwrite the client's version affinity cookie — silently switching users between versions.

At 50% rollout weight with ~15 chunk requests per page load, the probability of at least one chunk hitting the wrong deployment is 1 - 0.5^15 ≈ 99.997%. Effectively all users drift to one version, making weighted rollouts meaningless.

Expected: The __vdpl cookie should only be set on responses that go through application routing (page navigations, API routes, RSC payloads) — not on _next/static responses. Static asset responses should not establish or change version affinity because:

  • They may be served by a deployment that doesn't own that asset (404 during weighted routing)
  • A 404 response carries no meaningful "version assignment"
  • Only page-level responses where the server renders content should pin version affinity

Provide environment information

Next.js: 16.1.6
Deployment: Self-hosted on Kubernetes with weighted rollout strategy
Config: deploymentId: process.env.BUILD_ID, experimental.useSkewCookie: true
Output: standalone

Which area(s) are affected? (Select all that apply)

Headers, Cookies

Which stage(s) are affected? (Select all that apply)

Other (Deployed)

Additional context

The feature was introduced in https://github.com/vercel/next.js/pull/78841. The PR description notes the trade-off of "better caching" by using a cookie instead of ?dpl= query params, but the source: '/:path*' pattern was not scoped to exclude static assets.

This affects any self-hosted deployment where multiple versions serve traffic simultaneously with per-request routing — which includes any load balancer doing weighted distribution (ALB, nginx, HAProxy, Traefik, Kubernetes ingress controllers, etc.).

On Vercel this doesn't manifest because the routing layer reads the __vdpl cookie and pins requests to the correct deployment before they reach the server, preventing the 404 in the first place.

Proposed fix

Exclude _next/static from the cookie header source pattern:

  headers.unshift({
-   source: '/:path*',
+   source: '/((?!_next/static).*)',
    headers: [
      {
        key: 'Set-Cookie',
        value: `__vdpl=${config.deploymentId}; Path=/; HttpOnly`,
      },
    ],
  });

This mirrors the default Next.js middleware matcher convention, which already excludes this path.

extent analysis

TL;DR

Exclude _next/static from the cookie header source pattern to prevent version affinity cookie overwriting.

Guidance

  • Identify the load-custom-routes.ts file and locate the line where the source pattern is defined.
  • Update the source pattern to exclude _next/static using a negative lookahead regex, as shown in the proposed fix.
  • Verify that the updated pattern correctly excludes static asset responses from setting the __vdpl cookie.
  • Test weighted rollouts to ensure that version affinity is correctly maintained and users are not silently switched between versions.

Example

The proposed fix provides a code snippet that demonstrates the updated source pattern:

  headers.unshift({
-   source: '/:path*',
+   source: '/((?!_next/static).*)',
    headers: [
      {
        key: 'Set-Cookie',
        value: `__vdpl=${config.deploymentId}; Path=/; HttpOnly`,
      },
    ],
  });

This code update should be applied to the load-custom-routes.ts file.

Notes

This fix assumes that the issue is caused by the source pattern not being scoped to exclude static assets. If the issue persists after applying this fix, further investigation may be necessary.

Recommendation

Apply the proposed workaround by updating the source pattern to exclude _next/static, as this should prevent the version affinity cookie from being overwritten by static asset responses.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - ✅(Solved) Fix `useSkewCookie` sets `__vdpl` cookie on `_next/static` responses, breaking weighted deployments [1 pull requests, 1 comments, 2 participants]