Back to blog

Moving Next.js app from Vercel to Cloudflare

TL;DR: I moved this website (rumble-video.download) from Vercel to Cloudflare a while ago. This article explains why I made the switch, what I learned during the migration, and what it's been like running a Next.js app on Cloudflare ever since.

Introduction

rumble-video.download is something I work on after hours. It's a side project that downloads public content from platforms like Rumble, Kick, and Twitch.

This isn't a migration guide. Instead, I want to share the reasons behind the move, the lessons I learned, and my experience hosting a Next.js application on Cloudflare.

Like many Next.js apps, it started on Vercel. Deployment was incredibly smooth and everything worked out of the box. As more people started using the site, though, I eventually began hitting the limits of the free plan.

Vercel charges based on usage, and the first limit that became problematic was Edge Requests.

On the free plan you get 1,000,000 Edge Requests per month. At first glance that sounds extremely generous. Once you understand what actually counts as an Edge Request, though, those numbers can grow surprisingly fast as your website gains traction.

Initially I assumed an Edge Request was counted only when my application code executed. That's partially true, but requests for static assets such as images, JavaScript bundles, CSS files, and other static content are also counted.

For a commercial business this probably wouldn't have been a big deal. My app, however, is simply a fun side project. Rather than moving to a paid Vercel plan, I decided to see what else was available.

A new home: Cloudflare

Cloudflare immediately caught my attention because of its extremely generous free tier.

Before this migration I honestly hadn't used many Cloudflare products beyond the CDN. What convinced me was the combination of Cloudflare Workers and the open source OpenNext project, which makes it possible to run Next.js applications on Cloudflare's infrastructure.

The migration itself was much smoother than I expected.

What I like about Cloudflare

Whether these advantages matter depends entirely on your application. My downloader has a fairly unusual architecture, and it happens to fit Cloudflare's platform very well. More below!

1. Edge computation

The term edge has become a bit diluted lately, so let me quickly explain what I mean.

I simply mean executing code as close to the user as possible. Cloudflare Workers do exactly that by default. Your code runs on the nearest Cloudflare location instead of a single centralized region. Cloudflare currently operates servers in 330+ cities worldwide, which makes a noticeable difference for latency.

My application doesn't store any state and doesn't need a database for most requests. Every request simply fetches metadata from the target platform and returns a response. Because there's no central database involved, there's no reason to route everyone to a single region. The request reaches the closest Cloudflare location, the Worker does its job, and the response comes back quickly.

For this particular use case, Cloudflare seems a great fit.

2. A generous free tier

It's surprisingly easy to accidentally burn through Vercel's free limits, once you get some decent user traction. The internet is full of examples involving aggressive prefetching, proxy misconfigurations, or unexpected traffic patterns.

Cloudflare's free tier feels much more predictable.

You get 100,000 Worker invocations… per day 🤯, and an invocation refers to actual Worker execution. Loading static assets does not consume those invocations. For my application this pricing model makes much more sense.

3. The Cloudflare ecosystem

Although Vercel keeps expanding its product portfolio, Cloudflare has spent years building an ecosystem of services that integrate nicely with Workers.

Once I started using Workers, I naturally began exploring these services as well. As of today, my app is built mostly on top of Workers, Durable Objects and KV, R2. But theres loads of other products.

The not-so-good parts

Cloudflare isn't perfect, though. There are definitely some rough edges.

1. Developer experience

The developer experience still isn't quite at Vercel's level.

Every deployment revolves around a Wrangler configuration file wrangler.json.

It acts as the connection between your application and Cloudflare's infrastructure. You describe which resources your application needs, how they're bound, and how everything fits together.

After using it for a while it starts making sense, but I still feel that much of this configuration could eventually become automatic, inferred from a source code - this is something that people at https://voidzero.dev/ have started exploring, though.

It starts to click after you've used it for a while, but I still can't help thinking that much of this configuration should eventually be inferred directly from the source code. Thankfully, the folks at VoidZero have already started working on that.

The dashboard (Cloudflare UI) has improved significantly over time, but it still feels like a platform built around their broad infrastructure components rather than applications.

That's understandable. Hosting Next.js isn't Cloudflare's primary business. A Next.js app is ultimately just another Worker deployment. The result is that things like observability and application management are a little less polished than on Vercel.

At that front, I have to admit - Vercel's deployment and management experience was fantastic.

3. Next.js feature parity

OpenNext does an impressive job of keeping up with Next.js releases.

That said, new framework features rarely become available on day one. There's always a bit of lag while maintainers implement support.

For most projects this won't matter, but if you're constantly adopting the latest experimental Next.js features, it's something to keep in mind.

4. Worker bundle size

One limitation I ran into several times is the Worker bundle size. Cloudflare limits Worker bundles on the free plan to 3 MB compressed.

I exceeded that limit a few times, but every time I managed to solve it by removing unnecessary dependencies, splitting code, or otherwise optimizing the bundle.

In hindsight I'm actually glad this limit exists. It forced me to keep the application lightweight instead of resorting to plan upgrade (which still feels like nothing, comparing what you get in exchange).

5. The runtime environment

The generous free tier comes with one important tradeoff. Workers do not run in a traditional Node.js environment. Instead, they run inside the Chrome V8 runtime. That means you get excellent startup performance and low latency, but you also accept some runtime limitations.

Cloudflare has done an impressive job implementing Node.js compatibility, and the support improves constantly. Still, there are things that simply can't work because of the differences between V8 isolates and a full Node.js process.

If your application depends on native binaries like FFmpeg or other operating system features, Workers probably aren't the right environment.

Looking ahead

Over the past several months Cloudflare has made some interesting moves around the JavaScript ecosystem.

Ignoring the occasional public debates between Cloudflare and Vercel leadership on X, the more interesting story is where Cloudflare is investing.

They've been contributing to OpenNext, supporting the project financially, participating in the Next.js ecosystem working group, and investing in tooling around modern JavaScript development.

It's encouraging to see another serious platform investing in the Next.js ecosystem. Healthy competition benefits everyone, and it's good to have strong alternatives alongside AWS-based hosting providers.

Conclusion

If you've made it this far, you've probably realized I'm quite bullish on Cloudflare.

It's definitely not perfect. The dashboard still has room for improvement. The developer experience isn't as polished as Vercel's. The runtime has limitations that won't work for every application.

Despite all that, moving this project to Cloudflare has been a great decision. The platform fits my workload almost perfectly.

Back to blog