How to Deploy Next.js to Cloudflare Pages in 2026 (Step by Step)
We migrated our Next.js 14 app from Vercel to Cloudflare Pages. Here's the exact playbook, with cost and latency data.
How to Deploy Next.js to Cloudflare Pages in 2026
We migrated our Next.js 14 app (47 pages, ISR enabled, 2 edge functions) from Vercel to Cloudflare Pages. Here's the exact playbook — including cost, latency, and gotchas.
Why We Moved
Our Vercel bill hit $87/month for what we considered a small app:
- $42 from Image Optimization
- $31 from Edge Function invocations
- $14 from ISR cache misses
- A Cloudflare account (free)
- Next.js 14+ project
- A custom domain on Cloudflare DNS
- Workers & Pages → Create application → Pages → Connect to Git
- Select your repo
- Build command: npm run build
- Build output: .open-next/dist
- Root directory: /
- NEXT_PUBLIC_API_URL
- DATABASE_URL
(use Cloudflare Hyperdrive!) - Any secrets
- No build-time environment variables in edge runtime — use getCloudflareContext()
instead - ISR cache purge has 30s delay — not instant like Vercel
- No output: 'standalone'` support — must use OpenNext adapter
- Cloudflare Workers limit: 10MB bundle size (Vercel is 250MB)
- Database connections: use Hyperdrive, never connect directly to Postgres
- Your app is serverful (long-running WebSockets, etc.)
- You need bytecode-level custom Vercel integrations
- You use Vercel-specific features (Edge Middleware, Image Optimization specific tweaks)
- Cost-sensitive (saving >$50/month)
- Global audience (Cloudflare's edge network is unbeatable)
- Static-first apps
- You're hitting Vercel bandwidth limits
We tested Cloudflare Pages. After 30 days of production traffic, here's what we found.
The Migration (8 Steps)
1. Prerequisites
2. Install the Worker Adapter
Cloudflare's Next.js support is via the OpenNext Cloudflare adapter:
``bash
npm install @opennextjs/cloudflare
`
Add to next.config.js:
`js
import { initOpenNextCloudflareForDev } from '@opennextjs/cloudflare';
initOpenNextCloudflareForDev();
export default { /* your existing config */ };
`
3. Add the Build Script
`json
{
"scripts": {
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
"cf-typegen": "wrangler types --env-file=.env.production"
}
}
`
4. Configure wrangler.toml
`toml
name = "my-next-app"
compatibility_date = "2025-01-01"
compatibility_flags = ["nodejs_compat"]
pages_build_output_dir = ".open-next/dist"
[vars]
NEXTJS_ENV = "production"
`
5. Set Up Git Integration
In Cloudflare Dashboard:
6. Add Environment Variables
In Pages → Settings → Environment variables:
7. Configure Custom Domain
Pages → Custom domains → Set up a custom domain.
8. Enable Hyperdrive (for databases)
If you use Postgres/Neon, enable Hyperdrive for 10x latency reduction:
`toml
[[hyperdrive_bindings]]
binding = "HYPERDRIVE"
id = "your-hyperdrive-id"
`
Real-World Results (After 30 Days)
| Metric | Vercel | Cloudflare Pages | |--------|--------|-------------------| | Monthly cost | $87 | $0 (free tier) | | P50 latency (US) | 142ms | 78ms | | P50 latency (EU) | 189ms | 41ms | | P50 latency (Asia) | 387ms | 62ms | | Deploy time | 1m 12s | 1m 28s | | ISR support | ✅ | ✅ | | Edge runtime | ✅ | ✅ | | Image optimization | ✅ ($42/mo!) | ✅ (free) | | Bandwidth | $0.15/GB | Free |
The Gotchas
When NOT to Switch
When You Should Switch
TL;DR
We saved $87/month and got 2-6x faster latency globally. The migration took 4 hours. Worth it for our use case.
*Published 2026-09-13 by T2 Team · 8 min read*