Skip to content

Migrate from Vercel to Cloudflare Workers

Last updated View as MarkdownAgent setup

This guide shows you how to move an application from Vercel to Cloudflare Workers. Workers runs your framework's server code and serves its static assets from a single Worker.

Choose your framework

Each framework guide includes a prompt for your coding agent and the equivalent manual steps. Every guide was tested end to end by migrating a real Vercel-hosted application.

Framework Guide What changes
Astro Migrate Astro from Vercel @astrojs/vercel is replaced by @astrojs/cloudflare
Next.js Migrate Next.js from Vercel vinext runs your Next.js app on Vite and Workers
Nuxt Migrate Nuxt from Vercel The Nitro vercel preset is replaced by cloudflare_module
Remix and React Router Migrate React Router from Vercel @vercel/remix is replaced by the Cloudflare Vite plugin
SvelteKit Migrate SvelteKit from Vercel adapter-vercel is replaced by adapter-cloudflare
TanStack Start Migrate TanStack Start from Vercel The Nitro Vite plugin is replaced by the Cloudflare Vite plugin
Static site or single-page app Migrate a static site from Vercel A Wrangler configuration file points to your build output

For other frameworks, refer to the framework guides and the rest of this page.

Before you begin

These steps apply to every framework:

  • Install dependencies before you run any migration tool. Automatic project configuration cannot detect your framework without node_modules.
  • If you use pnpm 10 or later, allow the esbuild and workerd build scripts. Otherwise, installs fail with ERR_PNPM_IGNORED_BUILDS. Run pnpm approve-builds --all, or add the packages to allowBuilds in pnpm-workspace.yaml.
  • Set the Worker name explicitly. Migration tools default to the name field in package.json, which is often a template name.
  • Use a compatibility date of 2026-08-04 or later, for example today. Node.js compatibility is on by default for these dates, so new configurations do not need the nodejs_compat flag. Existing configurations can keep it. For more information, refer to Node.js compatibility flag.
  • Add .wrangler/ and .dev.vars* to .gitignore.
  • If your account has access to more than one Cloudflare account, set the CLOUDFLARE_ACCOUNT_ID environment variable before you deploy.

Migrate a static site or single-page application

To migrate a project that does not render pages on the server, refer to Migrate a static site or SPA from Vercel to Cloudflare Workers.

Map Vercel features to Cloudflare

Each Vercel feature has a Cloudflare equivalent:

Vercel feature Cloudflare equivalent
Analytics and Speed Insights Web Analytics
Blob R2
Cron Jobs Cron Triggers with a scheduled() handler
Edge Config Workers KV
Environment variables Environment variables and secrets
Functions, Edge Functions, Middleware One Worker, built by your framework adapter
Git integration and preview URLs Workers Builds and preview URLs
Image Optimization Images binding or image transformations
ISR and s-maxage caching Prerendering, or your framework's Cloudflare cache integration. Refer to Replace ISR and edge caching.
KV and Upstash Redis Workers KV, or keep Upstash and connect over HTTP
Postgres Keep your database and connect with Hyperdrive, or use D1
Queues Queues
vercel.json headers and redirects Framework configuration, or _headers and _redirects for static assets

Vercel-specific URLs, such as /_vercel/image and /_vercel/insights, return 404 after you migrate. Update any references to them.

Move environment variables and secrets

To copy production environment variables from Vercel to your Worker:

  1. Pull the production environment variables with the Vercel CLI:

    vercel env pull .env.production.local --environment=production

    Vercel does not return the values of sensitive environment variables. Add those values to the file manually.

  2. Upload the variables as Worker secrets:

    npx wrangler secret bulk .env.production.local
  3. Delete .env.production.local after the upload.

Store non-secret values in vars in your Wrangler configuration file. Store local development secrets in a .dev.vars file. Public build-time variables, such as NEXT_PUBLIC_*, VITE_*, and PUBLIC_*, must exist when your project builds. If you use Workers Builds, add them as build variables.

Restore caching for hashed assets

Vercel serves hashed build assets with a one-year immutable cache. Workers serves static assets with max-age=0, must-revalidate by default. To restore long-lived caching, add a _headers file to your static directory. Adjust the path to match your framework's asset directory:

public/_headerstxt
/assets/*
  Cache-Control: public, max-age=31536000, immutable

SvelteKit and Nuxt generate a _headers file for you. Cloudflare applies every _headers rule that matches a path. To replace a header value from a less specific rule, add ! Header-Name before the new value. For more information, refer to Headers.

Replace ISR and edge caching

On Vercel, a Cache-Control: s-maxage header caches server-rendered responses at the edge. On Workers, turn on Workers Cache to cache your Worker's responses based on the Cache-Control headers they return. Workers Cache requires Wrangler 4.69.0 or later.

{
	"cache": {
		"enabled": true,
	},
}
[cache]
enabled = true

Workers Cache does not serve stale responses that include s-maxage, even if they also set stale-while-revalidate. For more information, refer to Cache-Control semantics.

When caching is on, all requests to your Worker are billed at the standard request rate, including static asset requests. For more information, refer to Workers Cache pricing.

You can also prerender pages that do not change between deploys, use your framework's Cloudflare cache integration, such as Astro route caching or a vinext cache adapter, or use the Cache API from your server code.

Add a custom domain

Workers Custom Domains only supports domains that are configured as zones on your account. A zone is a domain, such as example.com, that Cloudflare manages for you, including its DNS and traffic.

To move a domain without downtime:

  1. Deploy your Worker and test it on its workers.dev URL. Keep Vercel serving production.
  2. Lower the time to live (TTL) of your DNS records.
  3. Add your domain to Cloudflare as a zone. Confirm that the imported DNS records match your Vercel records, then update the nameservers at your registrar.
  4. Add a custom domain to your Worker. The custom domain replaces the existing Vercel DNS record for that hostname and issues a certificate.
  5. Confirm that traffic reaches your Worker, then remove the domain from your Vercel project.

Roll back a deployment

To return to a previous version of your Worker, run:

npx wrangler rollback

To shift traffic gradually between versions, refer to Gradual deployments.

Delete your Vercel app

After your custom domain sends requests to Cloudflare Workers, you can delete your Vercel application.

Troubleshooting

  • Review the Workers limits. SSR applications usually need the Workers Paid plan, because the Free plan allows 10 ms of CPU time per request.
  • Native Node.js modules, such as sharp and canvas, do not run on Workers. Runtime writes to the file system also fail.
  • On a workers.dev URL, Cloudflare serves a managed robots.txt file if your application does not provide one.
  • For more migration steps, refer to the Cloudflare Pages to Workers migration guide.

Was this helpful?