What happens to the tab that was already open? A version-skew axis proposal (September 2026)
Deploying and then looking is one motion, so every client you observe loaded after your newest build. This proposal scores what happens to the tab that did not. Rubric and protocol published before any measurement.
Updated on September 26, 2026
On this page
Quick Answer
Version-skew posture is a proposed BuilderProof benchmark axis, drafted September 26, 2026, that measures what an AI app builder's generated application does to a browser that loaded it before the current deployment went live. It is scored from the untouched export and a two-phase probe: load the application, deploy over it, and then use the document that is still open. This page is a pre-registration rather than a report. It publishes a rubric and a protocol before any builder is measured against them, and it assigns no score to any vendor.
The problem this axis exists for
Ask an AI app builder to change something and it will change it, build it, and put the new version live. You look at the result. It is correct.
The person who has a problem is not you. It is the visitor whose tab has been open since before that deploy, whose browser is still running the JavaScript you shipped an hour ago, and who is about to click a menu item that lazily loads a file which no longer exists on the server. Nothing about that visitor is visible from where you are standing, because the act of deploying and then looking is a single motion that always produces a freshly loaded client.
This is not an exotic condition. It is what happens to every open session on every deploy, and the more often a builder ships, the more often it happens. What separates applications is not whether the transition occurs but whether anything in the generated code was written with the transition in mind.
What "version-skew posture" means here
The scope is deliberately narrow. This axis is about one document, already running old code, meeting a server that has moved on. It is read from the deployed artifact and its configuration, not from the builder's marketing.
It is not about whether the server can go back, not about whether the network is up, and not about whether two open documents agree with each other. Those are three different axes and the section below states each boundary in both directions.
Four documented facts that make this measurable
The useful thing about this axis is that it does not need a new experiment to establish that the failure is real. Two vendors document it, name it, and enumerate its symptoms in their own words.
1. The failure is named and enumerated by the framework itself
Next.js carries a glossary entry for it. Next.js, glossary, verbatim: "After a new version of your application is deployed, clients that are still active may reference JavaScript, CSS, or data from an older build. This mismatch between client and server versions is called version skew, and it can cause missing assets, Server Action errors, and navigation failures."
Its self-hosting guide breaks that into three named symptoms, and they are worth keeping separate because they fail in different layers:
- "Missing assets: The client requests JavaScript or CSS files that no longer exist on the server"
- "Server Function mismatches: The client invokes a Server Function using an ID from a previous build that the server no longer recognizes"
- "Navigation failures: Prefetched page data from an old deployment is incompatible with the new server"
The hosting platform describes the same class in a different register, and its example is a data-shape example rather than a missing-file one. Vercel, Skew Protection, verbatim: "Version skew occurs when different versions of your application run on client and server, causing application errors and other unexpected behavior. For example, imagine your newest deployment modifies the data structure by adding a required field to a user's profile. Older clients wouldn't expect this new field, leading to errors when they submit it."
Two independent vendors, two different failure classes, one named phenomenon. A benchmark axis does not have to argue that the problem exists.
2. The remedy covers framework-managed requests, and the platform says so plainly
The mechanism is a deployment identifier. The framework attaches it to requests as a dpl query parameter or an x-deployment-id header, and the server compares the client's identifier with its own.
Read what that covers. Vercel enumerates it as static assets, client-side navigations and prefetches, which it groups under the heading framework-managed requests. Then it states the gap itself, in bold on its own page: "The framework doesn't pin full-page navigations by default." And separately: "The framework doesn't automatically pin custom fetch() calls you make from client components."
That second sentence is the one that matters for a generated application. Route transitions are pinned for you. The calls the application's own business logic makes to its own API are not, unless somebody wrote the code to pin them. So the protection that reads like a checkbox covers the framework's traffic and leaves the application's traffic to the application.
The framework layer states a matching limit about routing. Next.js, deploymentId reference, verbatim: "A per-deployment value only avoids skew if requests are also routed by deployment. Next.js does not route on ?dpl=, so that routing comes from your host or CDN."
So the identifier is minted by the framework, the routing is performed by the host, and the application's own calls are the developer's problem. Three layers, each documenting itself correctly, and none of them owning the composition.
3. The remedy's own outcome is a reload, and the documentation says the reload loses state
This is the fact we think is genuinely unmeasured, and it comes from reading the remedy's own small print rather than from any new experiment.
When a mismatch is detected, the documented behaviour is not a graceful recovery. Next.js, verbatim: "If a mismatch is detected, Next.js triggers a hard navigation (full page reload) instead of a client-side navigation."
And immediately underneath, in the same document, the cost of that remedy is stated. Next.js, verbatim: "When the application is reloaded, there may be a loss of application state if it's not designed to persist between page navigations. URL state or local storage would persist, but component state like useState would be lost."
Read those two sentences together. The correct handling of version skew is an event that discards whatever the user had in progress, unless the generated application was built to survive it. A half-completed form, an open editor, a multi-step wizard on step four: all of it is component state, and component state is what the vendor says is lost.
Vercel names the same cost from the other direction when it documents the cookie you can set to opt out of the reload, listing its common use cases as live assessments and exams, real-time audio or video, and multi-step workflows. Those are exactly the applications for which the standard remedy is unacceptable.
4. The protection expires, and its expiry reproduces the symptom
Pinning is bounded in time, and the bound is short by default. Vercel, verbatim: "The default maximum age is one day from deployment creation."
What happens past the bound is the sharp part. Vercel, verbatim: "If a client requests a deployment that no longer exists or is older than the configured maximum age (via the ?dpl= query parameter, x-deployment-id header, or __vdpl cookie), the request returns a 404."
A 404 on a requested asset is the first of the three symptoms the framework enumerates. So the protection does not remove the failure mode, it buys a window and then hands the same failure back. A dashboard left open over a weekend is outside a one-day window by Monday morning.
Two further boundary facts belong on the record because a rubric that ignores them would be measuring the wrong thing. The feature is plan-scoped: "Skew Protection is available for all deployment environments for Pro and Enterprise teams." And it is on by default for recent projects: "Projects created after November 19th 2024 using one of the supported frameworks already have Skew Protection enabled by default." A generated application can therefore inherit this protection without anybody choosing it, or be structurally unable to have it, for reasons that have nothing to do with the quality of the generated code. Separating inherited from authored is what the posture ladder below attempts.
One oddity worth recording, because it is measurable and surprising: "Vercel automatically adjusts the maximum age to 60 days for requests from Googlebot and Bingbot to handle any delay between document crawl and render." Crawlers are granted sixty times the protection window that humans get by default.
The proposed rubric
Seven signals, weighted to 100. Each row states what a failing case looks like, so the rubric can be attacked before any vendor is measured against it.
Scroll to see more
| Signal | Weight | What a failing case looks like |
|---|---|---|
| Framework-managed requests carry a build identity | 22 | Assets and navigation data are requested by path alone, so a document loaded before the deploy asks the server for a file that no longer exists |
| The application's own client-side calls carry it too | 20 | Route transitions are pinned, while the app's own calls to its own API are not, so business logic written against the old contract talks to the new server |
| A mismatch produces a defined outcome | 16 | A lazily loaded module rejects, nothing catches it, and a menu item silently does nothing at all |
| In-progress user state survives the remedy | 14 | The documented remedy is a full reload, the reload discards component state, and a half-filled form goes with it |
| The protection window is stated and matched to real session length | 12 | A default window shorter than the sessions the interface invites, and the expiry returns a 404, which is the symptom the window existed to prevent |
| Server-side contracts tolerate an older client | 9 | A newly required field is added and submissions from clients that predate it are rejected rather than defaulted |
| Skew is distinguishable after the fact | 7 | Nothing in whatever error reporting exists separates a skew failure from an ordinary network failure |
Three weighting decisions worth arguing about now
Why the application's own calls sit almost as high as the framework's. Signal 1 is the better-known failure and scores highest, but signal 2 is the one the platform documentation explicitly declines to cover. A build can pass signal 1 entirely by inheritance, by being deployed on a host that turned the feature on, while failing signal 2 completely. Weighting them 22 and 20 says the inherited half and the authored half are close to equally important, and we would like the argument against.
Why state preservation is worth 14 rather than being someone else's axis. It is defensible to say that losing a form to a reload belongs to a resilience axis rather than here. We put it here because the reload is not an accident, it is the documented remedy, and an axis that rewards a remedy while ignoring the cost the vendor attaches to it is measuring half the transaction.
Why tolerating an older client is only 9. Backward-compatible server contracts are the deepest fix and arguably deserve more. It is scored lower because it is the hardest signal to read from an artifact without running the two-phase probe, and a rubric should not put its heaviest weight on its least reliable observation.
Four postures
The ladder is uneven on purpose, and we would rather say so than pretend the steps are equal.
- Unversioned. Requests identify resources by path alone. Nothing in the deployed artifact distinguishes one build from another, and a transition is simply an event the application has no representation of.
- Pinned by platform. Framework-managed requests carry a build identity, typically inherited from a host default rather than chosen. Full-page navigations, the application's own client calls, and long sessions are outside it.
- Pinned and bounded. As above, plus the application's own client-side calls carry the identity, and the protection window is a deliberate choice measured against how long the interface actually invites people to stay.
- Transition-safe. As above, plus in-progress work survives a forced reload, and a skew failure is distinguishable from a network failure in whatever error reporting the build ships.
The gap between 1 and 2 can be crossed by a billing plan. The gap between 2 and 3 cannot be crossed without somebody writing code. That asymmetry is the reason the ladder is worth four rungs rather than a single score.
The reproduction protocol
Ten steps. The axis is two-phase by construction, and step 3 is the step that makes the rest possible.
- Ask the builder for an ordinary feature with a multi-step form and at least one route that loads its code on demand. Do not mention deployments, versions or caching in the prompt.
- Export the untouched build. Record whether a deployment identifier appears anywhere in the configuration, and record a zero as a zero rather than as an absence of evidence.
- Open the deployed application in a real browser, navigate to the form, and fill it in partially. Leave the tab open and do not touch it again. Everything after this point is measured on that document.
- Ask the builder for a second change that alters a lazily loaded route, and deploy it. This is the transition. Confirm from a second, freshly opened browser that the new version is live.
- Return to the original tab. Navigate to the lazily loaded route. Record what happens: correct navigation, a full reload, a visible error, or nothing at all.
- Record whether the partially filled form survived whatever happened in step 5. This is the single observation most likely to differ between builds that otherwise score identically.
- Submit a request from the original tab to the application's own API. Record whether that request carried a build identity and whether the server accepted it.
- Inspect the network layer for the requests in steps 5 and 7. Record whether a deployment identifier travelled as a query parameter, a header, a cookie, or not at all.
- Repeat step 5 after the documented protection window has elapsed, so that the expiry path is measured rather than assumed.
- Search the build for any provenance of the behaviour: a configuration key, a comment, a written note. A correct outcome that nobody chose is inherited, and step 10 is the only step that separates the two.
The control that carries no information. Deploying and then loading the application in a new tab tells you nothing at all about this axis. Every request that document makes is already from the current build. It will pass every observation above, on a build at posture 1 and a build at posture 4 alike. It is recorded here as a control precisely so it is not mistaken for a test.
The named trap: the newest-client illusion
Every client you have ever observed of your own application loaded after your most recent deploy, because deploying and then looking is one motion. The cohort that experiences version skew is, by construction, the cohort you are never in.
An AI app builder sharpens this. The preview pane reloads on each change, so the loop continuously destroys the one condition the defect requires: a document older than the current build. The developer is not failing to look carefully. The developer is structurally unable to be the affected user without deliberately constructing a second phase that the build loop never produces on its own.
This is the same family as the illusions named in our other pre-registrations, where the only evidence available at test time comes from a single actor. This one has its own shape: the act that creates the stale cohort is the same act that puts you in the fresh one. You cannot be in both, and only a deliberate two-phase setup puts a document on the other side of the line.
What this axis is not
Not our rollback-safety axis. That axis asks whether the operator can return the server to an earlier version. This one asks what happens to a browser that is already running when the server moves to any other version, in either direction. Stated both ways: a build that scores full marks on rollback safety performs more version transitions, not fewer, and every restore is exactly the event that strands an open document, so the neighbouring remedy is this axis's triggering event rather than a mitigation for it. And a build with no rollback capability whatsoever can be perfectly skew-safe, because skew is a property of the client, not of the history mechanism. Read the rollback-safety proposal for what that axis does cover.
Not our client network-failure axis. That axis asks what the application does when the network is broken. This one asks what happens when the network is perfectly healthy and the server has simply moved on. Stated both ways: a build with flawless offline handling still fails here, and a build that handles every version transition gracefully still loses a form in a tunnel. The two genuinely compose, and the composition is sourced. MDN, on dynamic import, verbatim: "If module fetching and loading fails for any reason, rejects with an implementation-defined error (Node uses a generic Error, while all browsers use TypeError)", with the listed causes including both a failed network request and "an HTTP error occurs (404, 500, etc.)". A chunk that is missing because the deploy moved and a chunk that is missing because the connection dropped arrive at the application as the same rejection. The standard remedy for one is retry, and retry against an asset that has been permanently replaced will never succeed. Read the client network-failure proposal for the other half.
Not our multi-tab coherence axis. That axis is two documents at the same version disagreeing about state. This one is one document at an older version disagreeing with the server. Stated both ways: two tabs kept in perfect synchronisation with each other are no better off if both are running code the server has retired, because they are wrong in the same way at the same time; and a single tab with no second document anywhere still meets this failure on the next deploy.
Not a caching question, though caching is why it persists. Our HTTP caching proposal rewards marking fingerprinted assets as immutable, and that guidance is correct. It is also part of the mechanism here: the old document keeps working from its own correctly cached assets, which is precisely why it survives long enough to request a file the origin no longer serves. A correct caching posture makes the stale document more durable, not less.
A pinning question with a different counterparty. Our third-party script integrity proposal asks whether the bytes a third party serves you are the bytes you approved. This axis asks whether the bytes you serve are the ones the running client expects. Both are pinning questions and both carry the same tension in mirror image: pinning a third-party file by hash means the vendor cannot push you a fix, and pinning your own assets by deployment means your fix does not reach the client until it reloads.
The state that survives is a different axis's subject, and the vendor says so. The sentence quoted above names URL state or local storage as what persists across the remedy's reload. That is the subject of our URL-state addressability proposal: a build that keeps meaningful state in the address bar is, for reasons that had nothing to do with deployments, already substantially protected against the cost of a forced reload. That is a composition rather than an overlap, and it is documented by the framework rather than asserted by us.
Limitations and open questions
A rubric signal that could punish the better design, and how we rescoped it. A build that ships no lazily loaded routes, no client-side navigation and no client-side data fetching has essentially nothing to skew. Under a naive reading of signal 1 it would score blank, and a genuinely simpler architecture would be marked down against a more elaborate one that merely bought a hosting plan. Signals 1 to 3 are therefore scored as a full pass for a build with no such surface, and the limitation is stated here rather than left for a reader to discover. The rubric measures whether the transition is handled, not whether the application is complicated enough to need handling.
Inherited behaviour is hard to attribute and may be plan-scoped. A build deployed on a platform where this protection is on by default will score better than an identical build deployed elsewhere, for reasons unrelated to generated code quality, and the protection is documented as available to some billing tiers. Step 10 separates authored from inherited partially and not completely. This is the same attribution problem our caching and network-failure proposals both record, and we have not solved it in any of the three.
Step 9 is the least repeatable step. Waiting out a protection window before re-probing is slow, and a window can be reconfigured. A rubric whose sixth signal depends on its least convenient observation is a rubric with a practical problem, and we would rather flag that than quietly drop the row.
The two-phase probe is not free of confounds. Between step 3 and step 5 the browser may have discarded the page for reasons of its own. Distinguishing a genuine skew failure from an ordinary page discard needs care, and our protocol does not yet specify how.
We have measured nothing. Everything above is read from vendor documentation and reference material as of September 2026. Documentation is evidence of design intent, not of behaviour on a given run, and closing that gap is exactly what the protocol exists for.
Scope is browser-shaped. A native or mobile wrapper updates on a different cadence through a different channel, and none of this transfers.
What we are not claiming
We are not claiming that any builder ships this defect. No score is attached to any vendor on this page, and the rubric is published before any measurement precisely so it can be attacked first.
We are not claiming the documentation is at fault. Both vendors describe their own mechanisms accurately, enumerate their own limits, and in several places supply exactly the primitive an application needs. The gap this axis measures is in the generated code that does or does not pick those primitives up.
We are not claiming every application needs posture 4. A brochure site has nothing at stake in a deploy. What the axis measures is whether the handling matches what the interface is asking the user to trust it with.
Corrections, counterexamples from real deployed builds, and rubric edits are welcome, and the most useful thing you can send us is a step 6 observation from your own generated application: what was in the form after you came back to the tab.
References
- Next.js, glossary, version skew, accessed September 26, 2026.
- Next.js, self-hosting guide, Version Skew and Multi-Server Deployments sections, accessed September 26, 2026.
- Next.js, next.config.js deploymentId reference, last updated August 25, 2026, accessed September 26, 2026.
- Vercel, Skew Protection, last updated September 16, 2026, accessed September 26, 2026, including its How it works, Document navigations, Configure Maximum Age, Extending Skew Protection for long-lived sessions and Limitations sections.
- MDN, import(), Return value, accessed September 26, 2026.
Written by
BuilderProof editorial teamCite this benchmark
BuilderProof editorial team. "What happens to the tab that was already open? A version-skew axis proposal (September 2026)". BuilderProof, September 2026. https://www.builderproof.org/benchmarks/what-happens-to-the-tab-that-was-already-open-version-skew-axis-september-2026.
@misc{builderproof-what-happens-to-the-tab-that-was-already-open-version-skew-axis-september-2026,
title = {{What happens to the tab that was already open? A version-skew axis proposal (September 2026)}},
author = {{BuilderProof editorial team}},
year = {2026},
month = {sep},
howpublished = {\url{https://www.builderproof.org/benchmarks/what-happens-to-the-tab-that-was-already-open-version-skew-axis-september-2026}},
note = {BuilderProof, builderproof.org}
}Frequently asked questions
What is version skew in a generated application?
It is the state where a browser is still running code from an older build while the server has moved to a newer one. Next.js defines it in its own glossary: after a new version is deployed, clients that are still active may reference JavaScript, CSS or data from an older build, and that mismatch can cause missing assets, Server Action errors and navigation failures.
Does enabling skew protection on a hosting platform solve it?
Only partly, and the platform says so. Vercel documents that the framework does not pin full-page navigations by default, and that it does not automatically pin custom fetch calls made from client components. Framework-managed traffic is covered; the calls an application's own business logic makes to its own API are left to the application.
What does the standard remedy actually do to the user?
It reloads the page. Next.js documents that when a mismatch is detected it triggers a hard navigation instead of a client-side navigation, and in the same document notes that on reload there may be a loss of application state, with URL state or local storage persisting while component state is lost. A half-finished form is component state.
How is this different from the rollback-safety axis?
Rollback safety asks whether the operator can return the server to an earlier version. This axis asks what happens to a browser that is already running when the server moves to any other version. They pull in opposite directions: every restore is itself another version transition, so a build that scores well on rollback safety performs more of the events that strand an open document.
Have any builders been scored on this axis?
No. This page is a pre-registration. It publishes a seven-signal rubric, four posture levels and a ten-step two-phase protocol before any builder is measured against them, and it assigns no score, level or ranking to any vendor.
Related benchmarks
Rollback Safety: a proposed benchmark axis for AI app builders (July 2026)
A neutral BuilderProof proposal to score AI app builders on Rollback Safety across five documented sub-criteria. The finding: code version history is now table stakes, but data-layer rollback is the sub-criterion almost none of them document.
What Happens When the Connection Drops? A Proposed Axis for Client Network Failure Handling (September 2026)
A proposed benchmark axis for what a generated app does when the user’s own connection fails mid-action. The HTML Standard defines navigator.onLine so that true means "might be online", and the Fetch Standard defines a failed request as a response with status zero, no headers and no body. Seven weighted signals, four postures, a ten-step protocol, and no scores.
Who Can Change the Script After You Ship It? A Proposed Axis for Third-Party Script Integrity (September 2026)
A script element without integrity metadata does not request a specific script. It requests whatever the host at that address is serving when a visitor arrives. A pre-registration for a third-party script integrity axis, with the two specifications that make the half-fix fail harder than the no-fix.