nextjsboilerplate Docs
Deployment

Cloudflare Workers

Deploy to Cloudflare Workers via @opennextjs/cloudflare. Cheaper than Vercel at scale, edge-native, with caveats.

The honest pitch

Cloudflare Workers are dramatically cheaper than Vercel for most workloads and dramatically faster at the edge. They're also dramatically more constrained — no Node.js runtime, 50ms CPU per request on the free tier, no native filesystem.

@opennextjs/cloudflare is the adapter that translates a Next.js build into a Workers-deployable artifact. It's production-ready as of late 2024 and actively maintained.

When Cloudflare wins

  • High-RPS, low-latency, geographically distributed reads.
  • Static + ISR-heavy marketing pages.
  • A real edge story (think 50ms p99 globally).

When Cloudflare loses

  • Anything that depends on a long-lived Node connection (Sentry's session tracker, certain Postgres drivers, websockets-as-server).
  • Heavy server-side rendering with cold-start sensitive code paths (Workers cold-start fast, but the runtime mismatch with Node can surface dependencies that need polyfills).
  • File-based storage (use Cloudflare R2 instead — the boilerplate's Storage abstraction supports both S3 and R2 out of the box).

Setup

1. Install the adapter

npm install --save-dev @opennextjs/cloudflare wrangler --legacy-peer-deps

2. wrangler.toml

name = "my-saas"
main = ".open-next/worker.js"
compatibility_date = "2025-04-01"
compatibility_flags = ["nodejs_compat"]

[[d1_databases]]
binding = "DB"
database_name = "my-saas-db"
database_id = "<from wrangler d1 create>"

[[r2_buckets]]
binding = "STORAGE"
bucket_name = "my-saas-storage"

3. Build + deploy

npx @opennextjs/cloudflare build
npx wrangler deploy

Or wire it into package.json:

{
  "scripts": {
    "build:cf": "open-next build && wrangler deploy",
    "preview:cf": "open-next build && wrangler dev"
  }
}

Database options on Cloudflare

The boilerplate uses Drizzle on Postgres. On Cloudflare you have three choices:

  • Hyperdrive + Postgres — Cloudflare's Postgres connection pooler. Lowest-friction migration path. Drizzle schema works as-is.
  • Neon serverless driver — works inside Workers, no Hyperdrive needed. Same Drizzle code.
  • D1 (Cloudflare's SQLite) — radical change. Drizzle supports D1 but you'd need to translate every Postgres-specific feature (RLS, triggers, JSONB) to D1's SQLite. The audit-chain tamper-evidence safeguards in particular don't port — D1 has no row-level security. Not recommended unless you're building greenfield without the compliance primitives.

Storage on Cloudflare

R2 is S3-compatible. Set:

STORAGE_PROVIDER=r2
STORAGE_R2_ACCOUNT_ID=...
STORAGE_R2_ACCESS_KEY_ID=...
STORAGE_R2_SECRET_ACCESS_KEY=...
STORAGE_R2_BUCKET=my-saas-storage

The boilerplate's Storage.put() / Storage.getSignedUrl() work unchanged.

What about Sentry, PostHog, jobs

  • Sentry@sentry/nextjs ships an edge-compatible build. Source map upload works the same; runtime instrumentation works.
  • PostHog — client-side works fine. Server-side events go via the posthog-node SDK which supports Workers.
  • Jobs — Cloudflare deployments can use JOBS_PROVIDER=cloudflare-queues or a separate Railway/Node worker. src/jobs/registry.ts remains the canonical scheduled-job map.

What this is NOT

This is not "deploy to Cloudflare in 30 seconds." Cloudflare Workers add real constraints, and a multi-tenant SaaS with audit logs and webhook fan-out will hit some of them. Read the OpenNext compatibility matrix before committing.

For most teams, Vercel for v1, Cloudflare for v2 when scale economics demand it is the right call. The boilerplate doesn't lock you into either.

On this page