Skip to content

feat(start): add skew protection for server functions - #2363

Open
lxsmnsyc wants to merge 1 commit into
mainfrom
feat/server-function-skew
Open

lxsmnsyc wants to merge 1 commit into
mainfrom
feat/server-function-skew

Conversation

@lxsmnsyc

Copy link
Copy Markdown
Member

A page loaded before a deploy keeps calling server functions with the old client code. If a function's arguments or return value changed, or the function was removed, the call fails or does the wrong thing. This adds an opt-in check that refuses such calls and reloads the page so it runs the new version.

solidStart({ serverFunctions: { skewProtection: true } })
// several machines building one deploy:
solidStart({ serverFunctions: { skewProtection: { buildId: process.env.GIT_SHA } } })

Changes

  • Add serverFunctions.skewProtection. It is off by default and only applies to production builds.
  • Define import.meta.env.START_BUILD_ID for both the client and server environments. It is a random UUID per build, or the configured buildId. It is empty when the option is off or in dev, so the bundler drops the new code.
  • The client sends X-Start-Build with every server function call.
  • The server answers a call whose X-Start-Build differs from its own with 409 and X-Start-Skew: true, before the function is looked up or run. The response gets the default Cache-Control: no-store.
  • Requests without X-Start-Build are not checked. This covers no-JS form submissions and pages built before the option was turned on.
  • The client reloads the page on a skew response and leaves the call pending, so no error shows before the reload. It reuses recordReload() from the route chunk reload code. A second skew within 10 seconds rejects the call instead, so a load balancer that mixes old and new instances does not cause a reload loop.

The option is off by default because every deploy reloads every open page on its next server function call, even when that function did not change. Function IDs hash the file and the name, not the body, so a changed signature cannot be detected from the ID.

Testing

  • packages/start: tsc --noEmit passes and all 278 unit tests pass.
  • New unit tests cover the build ID define, the server check, and the client reload and its loop guard.
  • Built apps/fixtures/todomvc with skewProtection: { buildId: "build-a" }. The ID is in both the client and server output. A real server function called with X-Start-Build: build-a returned 200. The same call with build-old returned 409 with X-Start-Skew: true.
  • The reload was not tested in a browser.

🤖 Generated with Claude Code

- Add the `serverFunctions.skewProtection` option. It is off by default.
- Each production build gets an ID that both the client and server bundles share. A configured `buildId` replaces the random one.
- The client sends its build ID with every server function call.
- The server answers a call with a different build ID with 409 and does not run the function.
- The client reloads the page once on that response. A second skew within 10 seconds rejects the call instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8cf8ca9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solidjs/start Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify

netlify Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for solid-start-landing-page ready!

Name Link
🔨 Latest commit 8cf8ca9
🔍 Latest deploy log https://app.netlify.com/projects/solid-start-landing-page/deploys/6ad99fb3be84d20b5f74a156
😎 Deploy Preview https://deploy-preview-2363--solid-start-landing-page.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant