Web
We moved our Next.js app from Vercel to Cloudflare with vinext, and it got faster
DriveFlow runs on Cloudflare Workers with vinext since 27 October 2026. Here is what we measured against Next.js on Vercel, what we had to change for Workers, and what vinext still lacks.
DriveFlow has run on Cloudflare Workers since 27 October 2026, built with vinext instead of Next.js. Signed-in pages answer up to a third faster than they did on Vercel, and on a slow phone the main content shows up sooner on every page we tested.
DriveFlow is our platform for Swiss driving schools: 89 pages, 44 route handlers, a proxy.ts, Supabase auth and PDF invoices with a Swiss QR-bill. When we looked for someone who had moved an app like that, we found migration pull requests for demos and personal sites. So here is ours.
Why we moved our Next.js app off Vercel
One reason was money, the other was distance.
Vercel’s Hobby plan is for personal, non-commercial use. DriveFlow takes payments for driving schools, so going live meant Vercel Pro at $20 per developer seat per month.
Distance mattered more. Our Supabase database is in Zurich, and Vercel ran our functions in Frankfurt. proxy.ts calls supabase.auth.getUser() on every signed-in navigation, so each page an instructor opened waited on a trip from Frankfurt to Zurich and back. Cloudflare answers a Swiss visitor from its Zurich location, and the Worker runs there too.
What the move does not change is who you depend on. Vercel and Cloudflare are both US companies, and keeping processing strictly inside the EU on Cloudflare needs its Data Localization Suite, which is Enterprise only. The data that matters for residency was in Zurich before and still is. Where data is processed is the same question that decides whether you can run an AI model on customer data, which we went through in local AI models and Swiss data protection.
What vinext is, and how it differs from OpenNext
vinext is Cloudflare’s reimplementation of the Next.js API on Vite. It reads the same app/ directory, next.config.ts and next/* imports, and builds them into a Worker. OpenNext, the older route, takes the output of next build and translates it instead. We only tried vinext: 1.0 had just shipped, and npx vinext check rated DriveFlow 98 percent compatible. The missing two percent was Sentry’s build plugin.
The cost of vinext is plain. It is a second framework that has to follow every Next.js release, and it is young: 1.0 shipped on 28 September 2026, and we tested 1.3.0.
Vercel vs Cloudflare: the benchmark
Vercel ran the regular Next.js 16 build, Cloudflare the vinext build of the same commit, both against the same production database. A script requested each page 30 times with curl, alternating between the two hosts so both saw the same network, and signed in with real test accounts where a page needs it.
The largest gains are where we expected them. On signed-in pages the auth call is now a trip from Zurich to Zurich, and the owner’s finance page went from 185 to 125 ms.
In a real browser on a fast desktop connection the gaps were mostly small: the landing page drew its main content in 300 ms on Vercel and 308 ms on Cloudflare. The school profile was the exception, at 784 against 328 ms. On a throttled phone profile the difference became something you would notice.
Cloudflare sends more, though. On the phone profile the landing page was 818 KB in 102 requests, against 734 KB in 38 on Vercel. vinext splits JavaScript into many small chunks and prefetches the code of linked pages after load, so the first paint does not wait for it. The bytes are still real on a metered connection.
One setting is not optional. Our first build had image optimisation off, and the landing page sent 1,186 KB of images instead of 175 KB. With Cloudflare Images on, a 640 pixel screenshot came out at 23 KB as AVIF, against 24.5 KB as WebP on Vercel.
All of this comes from one machine in Switzerland on one evening, 26 October. It says a lot about Swiss users and nothing about anyone else.
What we had to change for Workers
Most of the work was not about vinext. It was about Workers, which is not Node.js: there is no file system and no child process, and fetch differs in places.
| On Vercel | On Cloudflare |
|---|---|
| pdfkit reads its font metrics from disk | pdfkit’s browser build, with Helvetica registered at startup |
Fonts and logos read with fs at request time |
The bytes inlined into the Worker at build time |
The service worker built inside a route with esbuild and git |
Built by a small Vite plugin after the client build |
fetch with redirect: "error" |
redirect: "manual", which Workers accepts and which still never follows a redirect |
The client IP from x-vercel-forwarded-for |
cf-connecting-ip |
| Vercel Cron | A scheduled handler in the Worker that calls the same route |
| Vercel Analytics and Speed Insights | Cloudflare Web Analytics, without cookies |
*.vercel.app previews are noindex by default |
Our proxy sends X-Robots-Tag: noindex on *.workers.dev |
Before the switch we went through every signed-in page as owner, instructor and student, and generated every file the app produces on both hosts. The same invoice with its QR-bill, once from Vercel and once from the Worker, side by side. A 200 tells you nothing about whether a PDF looks right.
What vinext does differently, and what it does not do yet
vinext itself gave us three small surprises. It refuses to build two pages that resolve to the same path, which Next.js allows; ours was an unused page in a route group, and we deleted it. It writes its immutable cache rule for hashed chunks into _headers only when that file does not exist yet, so a plugin that creates the file first leaves every chunk at max-age=0; our build now merges both rules. And it calls register() in instrumentation.ts without setting NEXT_RUNTIME, so @sentry/nextjs never started on the server, and @sentry/cloudflare took its place. None of the three was in the issue tracker when we searched on 27 October.
A few open issues are worth reading before you switch. Requests can get an empty 503 in the seconds after a deploy. There is no skew protection, so a tab opened before a deploy can ask for chunks that no longer exist, although Vercel Hobby had none either. Server Actions break in tabs opened before a deploy, which did not affect us because DriveFlow uses none. And some headers() patterns match differently from Next.js, so we checked ours on the trial and will again after every change to next.config.ts.
Vercel vs Cloudflare pricing for a small team
Vercel Pro is $20 per developer seat per month, with $20 of usage included. Workers Paid is $5 per month for the whole Cloudflare account, and requests answered from static assets are not billed. At DriveFlow’s traffic both stay at their base price, so the difference today is $15 a month per seat, and it grows with the team and the traffic.
The free Workers plan is not an option for an app this size. Our server bundle is 4.5 MB gzipped, and Workers Free allows 3 MB against 10 MB on Paid. The build got a little faster as well: 26 seconds locally instead of 34, and 58 to 75 seconds from push to production instead of 85 to 100.
Should you move your Next.js app off Vercel?
If your users and your database sit in one region and Vercel runs your functions in another, the move pays off in latency before it pays off in money. If your app leans on Server Actions or needs skew protection today, wait for those issues to close.
If you try it, keep to this order. Run npx vinext check. Deploy the same commit to a workers.dev URL and mark it noindex first. Benchmark both hosts interleaved, not one after the other. Then compare everything that produces a file, from PDFs to share images, side by side. No test suite does that last step for you.
Was moving off Vercel worth it?
For us, yes. The app is faster for the people who use it, and it costs less than the Vercel plan we would have needed. The account model settled it. Inviting my colleague Nino to the Cloudflare account cost nothing, so the two of us work in one account on one Workers Paid plan, for $5 a month for now. Cloudflare Tunnel is free as well and gives an internal service a public address without opening a port. So we did not stop at DriveFlow: the rest of our infrastructure moved to the same account.
Moving a production app without its users noticing is the kind of web development work we take on for agencies. The audit DriveFlow went through before its pilot is in what we check before a real business uses it.
the service behind this
The service behind this
Web Development in detailMost of the cost is in the second year, so we build for it.questions
Questions about this.
Is vinext ready for production?
What is the difference between vinext and OpenNext?
Is Cloudflare faster than Vercel for Next.js?
How much does Cloudflare Workers cost compared to Vercel?
Can a Next.js app run on the free Workers plan?
Tell us what you want to build.
Building something in this direction? Tell us what you want to build.