Users cannot navigate to URLs on older deployments after a new build is released #86074
Replies: 2 comments 3 replies
-
|
Hey @ozgurozalp 👋 I’ve faced this issue too when dealing with Next.js client navigation after new deployments. What’s happening here is that when a user is still on an older deployment, their browser is using the previous build’s JavaScript bundle (which references that build’s routes and chunk files). Then, when they click a link, the Next.js router tries to prefetch or load chunks from the new build — but since the current HTML was generated from the old build, the router gets confused and hangs. Even though you’ve stored all build assets in Cloudflare R2 (which is great), the browser is still trying to fetch assets with the new build ID, not the one it originally loaded with. ✅ The Root CauseNext.js uses a build ID to ensure consistency between server and client bundles. When a new deployment happens:
🧩 The Fix1. Serve old HTML with its matching build IDSince you already keep all build assets in R2, the key is to also serve the HTML (or app shell) that matches that specific build ID. Basically: That way, even old sessions can navigate freely without breaking. 2. Avoid serving mixed buildsMake sure your CDN or edge function doesn’t serve new HTML that references new bundles to a user still using an old app shell. Then have the client stay within its build scope until it reloads. 3. (Optional) Smoothly upgrade usersIf you want users to eventually move to the new version, you can add a lightweight version check — for example: setInterval(async () => {
const res = await fetch('/api/version')
const latest = await res.text()
if (latest !== window.__NEXT_DATA__.buildId) {
// optionally show "New version available" toast
}
}, 60000)This way, you’re not forcing a refresh but can gently prompt users. 💡 TL;DR
Once HTML and JS versions are aligned per build, navigation on old deployments will work perfectly without forcing refreshes. |
Beta Was this translation helpful? Give feedback.
-
|
You can still apply this approach even if most of your pages are dynamic. With dynamic routes, the key is: Always render the dynamic page using the same build version as the clientAs long as you version your SSR entry point by build ID (just like your static assets), you can serve: Your Cloudflare Worker (or whatever layer sits in front) just needs to:
This keeps navigation consistent because: So yes — even dynamic pages can be versionedThe dynamic logic (database queries, auth, etc.) stays the same. You’re only making sure the React runtime + RSC structure that wraps the dynamic data comes from the correct version. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
When they click on links, the page doesn’t load and gets stuck
We don't want to refresh page
Additional information
No response
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions