Prerequisites
- A Cloudflare account with Workers enabled (the free plan is enough for a staging deploy).
wranglerCLI authenticated:pnpm dlx wrangler login.- Your Cloudflare account ID (dashboard → right sidebar).
- A serverless-friendly Postgres pooler URL — Workers cannot hold long-lived TCP connections, so direct DB URLs are out. Good options: Neon serverless driver (HTTP-based), Supabase pgbouncer (transaction mode), or a hosted PgBouncer.
- Your existing env values from the Vercel deploy (you’ve already shipped on Vercel, right?). Vercel deploy guide first.
wrangler.toml.example at the root — copy it, don’t write one
from scratch.
Step-by-step
1. Install the OpenNext Cloudflare adapter
.open-next/worker.js.
2. Create your wrangler.toml
name— your Worker’s name (lowercase, dash-separated).account_id— uncomment and paste your Cloudflare account ID.
compatibility_date, nodejs_compat flag, the
.open-next/assets binding, and an [assets] block. Don’t change those unless
you know why.
3. Switch to a serverless-friendly DB pooler
Workers run for milliseconds and tear down — the classicpg driver dies on
cold starts. Pick one:
src/db/index.ts to drizzle-orm/neon-http or
drizzle-orm/postgres-js configured for pooled mode. The pg driver does not
work on Workers.
4. Push secrets via wrangler
Never commit secrets towrangler.toml. Push each one:
NEXT_PUBLIC_* ones) live under [vars] in wrangler.toml —
they’re shipped in the client bundle anyway, so no harm.
5. Build and deploy
https://<your-worker-name>.<your-subdomain>.workers.dev. Custom domains attach
through the Cloudflare dashboard (Workers & Pages → your worker → Custom Domains).
6. Re-point payment webhooks
Same drill as Vercel: in your payment provider’s dashboard, change the webhook endpoint URL to the new Workers domain. Verify the signing secret you pushed viawrangler secret put matches the value the dashboard expects.
Verify it works
Identical checklist to the Vercel deploy:https://your-worker.workers.dev/— home rendershttps://your-worker.workers.dev/api/ping—{ ok: true }https://your-worker.workers.dev/sitemap.xml— populated- A real $1 test charge →
paymentrow appears within 5s.
Common pitfalls
- Long-lived DB connections. The number-one mistake. Workers cannot hold a pool — every request is a new isolate, and TCP sockets vanish at the end. Use Neon’s HTTP driver or Supabase’s pgbouncer URL. Symptom: random 522 / 524 errors under load.
- Missing
nodejs_compatflag. Already present in the shipped config; if you removed it, webhook signature verification (node:crypto) explodes at runtime. - Node-only deps. Audit your dependencies with
pnpm dlx knipbefore deploying. Anything that importsfs,child_process,net, orworker_threadswill silently break. The scaffold itself is clean — third-party libs you add are the risk. - KV consistency confusion. Workers KV is eventually consistent. Don’t use it as the source of truth for auth sessions or payment idempotency. Postgres remains the source of truth for everything ledger-shaped.
- Wrangler
varsvssecrets.[vars]are public (shipped in source).wrangler secret putis encrypted. PuttingSTRIPE_SECRET_KEYin[vars]is a wallet-emptying mistake. - Deploy size limits. Free Workers plan caps at 1 MB compressed. OpenNext hits this fast — bump to the Paid plan ($5/mo, 10 MB) before you ship anything with images or fonts.
Official docs
- Cloudflare Workers: developers.cloudflare.com/workers
- OpenNext Cloudflare adapter: opennext.js.org/cloudflare
- Wrangler CLI reference: developers.cloudflare.com/workers/wrangler
- Neon serverless driver: neon.tech/docs/serverless/serverless-driver
- Supabase pgbouncer: supabase.com/docs/guides/database/connecting-to-postgres#connection-pooler