Skip to main content

Version Skew

What is Version Skew?

When you push a new frontend deploy to production, some users might still have an older page open in their browser. If that older page starts making backend requests, or requesting frontend data like dynamically loaded files, the app can break in odd ways.

That mismatch is called version skew: the browser is running one version of your app while the server is serving another.

Roundrobin helps with version skew by injecting a platform-managed DEPLOY_ID environment variable into every deployment. It is available during the build and at runtime, and it changes on every new deploy, including redeploys of the same commit.

Why protect against Version Skew?

You might be interested in protecting against Version Skew if your app has a heavy frontend, serves frontend assets or client-side navigation state that can become inconsistent across deploys.

Typical signs of version skew are:

  • a user refreshes or navigates after a deploy and gets missing chunk errors
  • an older tab keeps running but starts talking to a newer deployment
  • you need a reliable release identifier in logs, support diagnostics, or cache keys

If your app is a simple backend service with no browser-delivered frontend, you may not need any special handling beyond exposing the deploy ID in diagnostics.

Roundrobin's DEPLOY_ID

DEPLOY_ID is a platform-managed identifier for the current deployment. It is available at build time and runtime, and it changes for every deploy, even re-deploys.

Next.js

Next.js has built-in support for version skew protection through deploymentId in next.config.js.

If you run Next.js on Roundrobin, this is the recommended setup:

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  deploymentId: process.env.DEPLOY_ID,
};

export default nextConfig;

This lets Next.js tag client navigation and asset requests with the current deployment identity. When a user has an older page open during a rollout, Next.js can detect that the deployment changed and recover more cleanly instead of mixing old client state with new server assets.

If you do nothing, your app may still work most of the time. The problem is that deploy-time breakage becomes more likely and harder to reason about, especially for apps with active client-side navigation.

Next.js also supports NEXT_DEPLOYMENT_ID, but Roundrobin exposes the generic DEPLOY_ID so other frameworks can use the same platform contract.

Other frameworks and apps

DEPLOY_ID is useful as the current release identifier for your app to protect from version skew.

One practical pattern is to expose it in a header in the backend:

app.use((_req, res, next) => {
  res.setHeader('x-deploy-id', process.env.DEPLOY_ID ?? 'unknown');
  next();
});

You can also include it in a /health or /version endpoint:

app.get('/health', (_req, res) => {
  res.json({
    status: 'ok',
    deployId: process.env.DEPLOY_ID,
  });
});

app.get('/version', (_req, res) => {
  res.json({
    deployId: process.env.DEPLOY_ID,
  });
});

How the deploy ID affects version-specific behavior depends on your framework and application code.

© Roundrobin