All posts
Web design & development

Hosting a Next.js Site on Cloudflare Workers: A Practical Guide

How to host Next.js on Cloudflare Workers with the OpenNext adapter: setup, D1 and R2 bindings, edge caching, and the gotchas from our own production site.

By Mehdi Hassan7 min read

The short answer

To host Next.js on Cloudflare Workers, install the OpenNext Cloudflare adapter, configure wrangler with the nodejs_compat flag and an assets binding, add bindings for any database, storage or images you use, build with the adapter, test locally in workerd, and deploy with wrangler. Plan for Workers limits: no sharp, CPU time caps, and adapter-pinned Next.js versions.

Key takeaways

  • Workers, not Pages, is Cloudflare's recommended home for new full-stack Next.js sites.
  • The OpenNext adapter turns a Next.js build into a Worker; pin Next.js and the adapter together.
  • Use D1 for a database, R2 for uploads and cached pages, and the Images binding instead of sharp.
  • A CMS admin or heavy server work needs the paid Workers plan because of CPU time limits.
  • Cache pages at the edge and rebuild them in the background, so most requests never run server code.

Part of Website Hosting for Startups: What You Need and What You Don't

Why host Next.js on Cloudflare Workers?

Hosting Next.js on Cloudflare Workers gives you low running costs and code that runs close to visitors worldwide, with a database, file storage and image resizing on the same platform. Cloudflare is generally the cheapest of the main frontend hosts, and for new full-stack sites it now recommends Workers over Pages.

We run our own site, designify.design, this way: Next.js and Payload CMS on Workers, with content in D1 and uploads in R2. This guide is what we learned building it, including the parts that took longer than expected. It's not the easiest path to hosting Next.js; for the trade-offs against other hosts, see our website hosting guide for startups and the Vercel vs Netlify vs Cloudflare comparison.

What do you need before deploying Next.js on Cloudflare?

You need a Cloudflare account, the wrangler command-line tool, a Next.js app that doesn't depend on Node-only native libraries, and a decision about which Workers plan you'll use. The free plan works for mostly static sites; anything with real server work, such as a CMS admin, needs the paid plan.

  • Check your dependencies. Native Node modules, such as the sharp image library, don't run on Workers. Find replacements before you start.
  • Know your rendering. Static and cached pages are cheap and fast. Pages rendered on every request use CPU time on each visit; see static vs server rendering in Next.js.
  • Pick the plan. On our own site, the free plan's CPU time per request was far too little for the Payload admin, its API and background page rebuilds.
  • Read the official guide. Cloudflare's Workers documentation covers the current Next.js setup.

How do you deploy Next.js on Cloudflare Workers?

You deploy by adding the OpenNext Cloudflare adapter to your project, configuring wrangler, building with the adapter and deploying the resulting Worker. These are the steps we follow.

  1. Install the adapter and wrangler

    Add @opennextjs/cloudflare and wrangler to the project. The adapter converts the Next.js build output into a Worker plus static assets.

  2. Configure wrangler

    In wrangler.jsonc, set the Worker entry, turn on the nodejs_compat compatibility flag, and add an assets binding pointing at the adapter's assets folder.

  3. Add bindings

    Declare the D1 database, R2 buckets and Images binding your site uses, then generate TypeScript types for them.

  4. Configure caching

    In open-next.config.ts, choose an incremental cache. We use R2 for cached pages with a regional cache in front.

  5. Preview locally

    Build with the adapter and run the Worker locally in workerd, Cloudflare's runtime, before deploying. Plain next dev won't catch Workers-only problems.

  6. Deploy

    Run any database migrations first, then build and deploy with the adapter. We script both as one deploy command.

How do you add a database, storage and images?

On Workers you add services through bindings: D1 for an SQLite database, R2 for file storage, and the Images binding for resizing. Each binding appears in your code as an object on the environment, with no connection strings to manage.

Need

Cloudflare service

How we use it

Database

D1

Payload CMS content, with point-in-time restore

Uploads

R2

Images and videos uploaded in the CMS, stored as-is

Image resizing

Images binding

Resizes uploads on request to AVIF or WebP; replaces sharp

Page cache

R2 plus regional cache

Stores prebuilt pages for the edge cache

Backups

R2 and a cron trigger

A nightly copy of every table and upload

Images need the most thought. Because sharp can't run, we store uploads unchanged and serve them through a media route that resizes on request with the Images binding, saving each size back to R2 the first time it's made. In production the Worker answers media requests itself, before Next.js loads, which keeps them fast.

Deep dive: running Payload CMS on Workers

Payload adds a few extra requirements. Password hashing needed a patch, because Workers caps the PBKDF2 iteration count below what Payload uses by default, so sign-up and login failed until we patched it. GraphQL isn't fully supported on Workers yet, so we disabled it and use the REST and Local APIs.

The build loads the Payload config, which connects to remote D1 and R2 bindings, so builds must run somewhere signed in to Cloudflare or with an API token. We also made the build work without the Payload secret so automated builds can run. And we build with webpack, as Payload's official Cloudflare template does, because the adapter couldn't yet resolve Turbopack's server output. More in our Payload CMS marketing site write-up.

How do you cache Next.js pages at the edge on Cloudflare?

Cache pages by prebuilding them and storing them in the adapter's incremental cache, then letting Next.js revalidate them in the background. Visitors get a cached page; the Worker rebuilds it after content changes without anyone waiting.

On our site, home and case-study pages revalidate after about a minute, so an edit in the CMS shows up shortly afterwards while almost every request is served from cache. We also key the page cache on the deployed version, so a new deploy never serves pages built by old code. Caching is what keeps CPU time, cost and response times low. For the concepts, see CDN and edge caching.

What are the limits of Next.js on Cloudflare?

The main limits are CPU time per request, Worker size, Node compatibility and adapter timing. None stopped us, but each one cost time, and a team without a developer shouldn't take them on alone.

Pros

  • Low running costs for typical marketing-site traffic
  • Database, storage, images and cron on one platform
  • Code and cache close to visitors worldwide

Cons

  • The free plan's CPU limit is too small for a CMS admin or heavy server work
  • Large apps need the paid plan for Worker size too
  • Native Node libraries like sharp don't run
  • New Next.js releases wait for adapter support

Plan maintenance with this in mind: Next.js, the adapter and your CMS all move quickly, so upgrades are a regular task. Our guide to Next.js maintenance covers a schedule. If performance is your reason for choosing Cloudflare, remember most Core Web Vitals gains come from the front end, as covered in Core Web Vitals fixes for Next.js sites.

Should you use Cloudflare Pages or Workers for Next.js?

Use Workers for a Next.js site that does any server work, and for new projects in general, since that's where Cloudflare now points full-stack frameworks. Pages still works for fully static exports, where Next.js outputs plain HTML files.

Frequently asked questions

Does Next.js middleware work on Cloudflare Workers?
Middleware generally works through the OpenNext adapter, since Workers is already an edge runtime, but check the adapter's current documentation for any features it doesn't support yet. Test redirects, rewrites and any A/B testing logic in a local workerd preview before deploying, because next dev runs in Node and won't show Workers-specific problems.
Can I use Next.js image optimization on Cloudflare?
Not with the default sharp-based optimizer, because sharp doesn't run on Workers. Instead, use Cloudflare's Images service, either through the Images binding in your own route or a custom image loader. We resize uploads on request with the binding, serve AVIF or WebP, and save each resized version to R2 so it's only made once.
Is Cloudflare cheaper than Vercel for Next.js?
For most marketing sites, yes. Cloudflare is generally the cheapest of the main hosts, and its usage-based pricing doesn't grow with team size the way per-seat pricing does. The trade-off is setup and maintenance time for the adapter and platform limits, so compare running costs against the developer hours each option needs, not just the hosting bill.
Can I preview a Cloudflare deployment before it goes live?
Yes. Workers can upload new versions with preview URLs, and you can connect a Git repository so branches and pull requests get their own preview builds. Locally, building with the adapter and running the preview command runs your site in workerd, which is the most reliable way to catch Workers-only issues before deploying.

· CEO & Design Director

Copywriter, designer and developer, and founder of Designify Studio. Over five years, 60+ projects across 14+ industries, for startups that have raised $300M+.

Want this done for you? Website, $8,000.

A multi-page marketing site, designed by us, developed in Next.js and animated. $8,000, one-time, up to 6 pages. Book a free 30-minute call to see if it fits.

Schedule Call