If you’ve ever tried deploying a Next.js app to Cloudflare Workers, you’ve probably noticed a gap: Next.js expects Node.js APIs, while Workers traditionally run in a restricted edge runtime.
Enter OpenNext. With the @opennextjs/cloudflare
adapter, you can run your Next.js app on Workers using the Node.js runtime, giving you access to many familiar Node APIs — something @cloudflare/next-on-pages
can’t provide.
In this guide, we’ll walk through deploying a Next.js app to Cloudflare Workers using OpenNext, step by step.
⚖️ Edge Runtime vs Node.js Runtime
Aspect |
Edge Runtime (@cloudflare/next-on-pages ) |
Node.js Runtime (@opennextjs/cloudflare ) |
---|---|---|
Speed / Weight | Super fast, lightweight | Fast, slightly heavier |
Next.js Features | Limited; some features won’t work | Most features supported (SSR, ISR, middleware, streaming) |
Node.js APIs | Very restricted | Many supported via Workers’ Node.js compatibility |
TL;DR: Use Node.js runtime if you need full Next.js features and Node API support; Edge runtime is great for ultra-lightweight functions.
🚀 Let’s Dive In: Creating or Using a Next.js App
Option 1: Start a new Next.js app preconfigured for Workers
If you’re creating a new project, OpenNext can scaffold everything for you:
npm create cloudflare@latest -- my-next-app --framework=next --platform=workers
Option 2: Use with an Existing Next.js App
Step 1: Install the Cloudflare Adapter
npm install -D @opennextjs/cloudflare wrangler
Step 2: Create wrangler.jsonc
(optional)
This file will be auto-generated if not present during build. The nodejs_compat flag enables Node.js APIs in Cloudflare Workers.
{
"$schema": "node_modules/wrangler/config-schema.json",
"main": ".open-next/worker.js",
"name": "demo-app",
"compatibility_date": "2025-08-31",
"compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS"
},
"services": [
{
"binding": "WORKER_SELF_REFERENCE",
"service": "demo-app"
}
]
}
Step 3: Create open-next.config.ts
(optional)
This file will also be auto-generated if not present during build. The R2 incremental cache is optional and requires R2 enabled on your Cloudflare account.
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";
export default defineCloudflareConfig({
incrementalCache: r2IncrementalCache,
});
Step 4: Update package.json
Scripts
{
"scripts": {
"dev": "next dev",
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
"upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload",
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
}
}
Step 5: Remove export const runtime = "edge";
Edge runtime is not supported with @opennextjs/cloudflare
. Make sure to remove this line from any of your source files before deploying.
This ensures your app runs in the Node.js runtime, which is fully compatible with OpenNext and Cloudflare Workers.
Step 6: Update .gitignore
Add .open-next
to your .gitignore
file to prevent the build output from being committed.
Step 7: Add Static Asset Caching
Create a public/_headers
file with the following content:
/_next/static/*
Cache-Control: public,max-age=31536000,immutable
This ensures that your static assets (JS, CSS) are cached for one year, improving performance for repeat visitors.
Step 8: Preview and Deploy
Preview your app locally first:
npm run preview
Then deploy to Cloudflare Workers:
npm run deploy
⚠️ Next.js Version & Known Issues
If you run into errors like:
NextJS request failed. Error: An error occurred while loading the instrumentation hook
at NextNodeServer.loadInstrumentationModule
This is a known issue (GitHub #667).
The workaround is to downgrade your Next.js version to 15.3.
Other known issues and limitations with OpenNext on Cloudflare Workers can be found here:
OpenNext Cloudflare Known Issues
Top comments (0)