Vercel vs Cloudflare for Next.js

← All posts

Vercel vs Cloudflare for a static Next.js site: what I measured from Nairobi

By Kai Khalid, Nairobi · · 6 min read

ShareLinkedInXWhatsAppFacebook
Title card reading Vercel vs Cloudflare: almost the same for a personal site, with two boxes labelled Vercel Hobby and Cloudflare on a platform. Beside it: first byte from Nairobi, page load (Lighthouse) and a 34-location global test are what I measured.
Diagram 1

I'm Kai Khalid, in Nairobi, and I run my own website the way I'd want an operations team to run anything: write down what "better" means before you look at the numbers. This is the field report from moving kaikhalid.com off Vercel and onto Cloudflare, with what I measured, what broke, and what the data does not show.

What I moved

kaikhalid.com is a 14-page Next.js 16 portfolio. It needs no server, so I built it with output: 'export' (Next.js static exports): 173 files, about 6 MB. On Cloudflare it runs as Workers static assets, deployed by Workers Builds on each push. Deploys took 58.5–71.5 seconds.

Three changes were needed:

  • Images. A static export can't use Vercel's /_next/image optimiser. I replaced it with a 118-line build-time script that converts images to WebP using sharp at quality 75. 44 files came out byte-identical to the originals.
  • Headers. HSTS and cache rules moved into a _headers file.
  • Redirects. The www → apex redirect became a Cloudflare dashboard rule.

How I tested

  • Same code on both hosts: the same build, deployed to Vercel and Cloudflare.
  • One machine: a Mac on one network in Kenya, on 16 October 2026.
  • Pre-registered decision rule: Cloudflare "wins" only if Lighthouse LCP is better by more than 100 ms in at least 3 of 4 cells (mobile/desktop × home/post page).
  • TTFB: fresh connection each time, DNS excluded, 100 interleaved pairs × 2 rounds. 1,200 requests in total, all HTTP 200 with a cache HIT.
  • Lighthouse: Lighthouse 13.5.0, simulated throttling, 10 runs per cell.
  • Noise control: an A/A test (same host vs itself) gave a noise floor of about ±70 ms on desktop and ±400 ms on mobile.

Results: time to first byte (from Kenya)

MetricVercelCloudflareDifference
Median TTFB~302–328 ms47–59 ms~246–262 ms faster on Cloudflare
Pairs where Cloudflare was faster–95–99%–
TLS handshake200 ms21 ms179 ms
Server wait111 ms24 ms87 ms
Edge that served the requestCape Town (cpt1)Nairobi (NBO)–

Most of the gap is geography. A TLS handshake needs round trips, and round trips to Cape Town cost more than round trips across town.

Stylised map of Africa. An orange arrow runs from Nairobi (my desk) to NBO, Cloudflare, a short hop on the east coast. A white arrow runs from Nairobi down to CPT1, Vercel, Cape Town at the southern tip. Text on the left: about 250 ms faster first byte, from my desk in Nairobi.
Diagram 2
Stacked blocks per host. Vercel: TLS handshake 200 ms with server wait 111 ms on top, a tall stack. Cloudflare: TLS handshake 21 ms with server wait 24 ms, a low stack. Text: 1,200 requests, every one a 200, every one a cache HIT.
Diagram 3

Results: Largest Contentful Paint (Lighthouse, simulated)

CellVercel LCPCloudflare LCPCloudflare advantageScores (V / CF)Clears 100 ms bar?
Mobile, home2954 ms2280 ms+675 ms88.5 / 98Yes
Mobile, post3094 ms2563 ms+531 ms88 / 97Yes
Desktop, home529 ms607 ms−79 ms100 / 100No
Desktop, post519 ms595 ms−77 ms100 / 100No

Two caveats matter. The mobile gains sit inside a ±400 ms noise floor, though both are larger than it. The desktop lead for Vercel is only just outside the ±70 ms floor.

Four tiles for the four Lighthouse cells. Green, Cloudflare ahead by more than 100 ms: mobile home +675 ms and mobile post +531 ms. Red, Vercel ahead: desktop home and desktop post, about 77–79 ms. Result: 2 of 4, verdict partially supported. The rule, written first: Cloudflare wins only if LCP is better by more than 100 ms in at least 3 of 4 cells.
Diagram 4
Number line of the desktop LCP difference in ms from −100 to +100. A shaded band marks the noise floor of about ±70 ms. A marker for the Vercel lead of 77–79 ms sits just beyond the band. Text: still unexplained, even after blocking Cloudflare's injected analytics beacon.
Diagram 5

Cloudflare injects a Web Analytics beacon (10.4 KB, 4 requests). Blocking it did not close the desktop gap, so the cause is still unexplained. Unthrottled desktop runs pointed the other way: home LCP 676 ms on Vercel vs 361 ms on Cloudflare (significant), post 810 vs 371 ms (not significant).

Outside Kenya

A 34-node global checker found Cloudflare faster in 23 locations and Vercel in 11, with a median of 49 ms in Cloudflare's favour. Vercel was faster in parts of western Europe (Germany: 49 ms vs 154 ms) and in Hong Kong. If your audience is mainly in Frankfurt, test from there before you decide.

Grid of pillars, one per location, from the 34-node global checker. 23 orange pillars are labelled Cloudflare faster and 11 white pillars are labelled Vercel faster. Text: Vercel won in parts of western Europe (Germany 49 vs 154 ms) and Hong Kong. Cloudflare is faster for Kenyan visitors in my test; elsewhere it is mixed.
Diagram 6

Migration gotchas

  • Error 100117 when attaching the custom domain. Cloudflare refuses if an existing A or CNAME record is already on that hostname. Remove the old record, then attach.
  • The www redirect is now invisible from the repo. It lives in a dashboard rule. That's a configuration drift risk: anyone reading the code won't know it exists. Document it, or move it into code.
  • Free-tier terms. Vercel's Hobby plan is for non-commercial, personal use, and keeps runtime logs for only one hour. See Vercel pricing. I have not yet checked Cloudflare's free-plan terms in the same detail. Do that before you rely on it.
  • Image optimisation is now your job. No /_next/image in a static export, so plan a build step.

Which should you choose?

If…Lean towards
Most visitors are in Kenya or East Africa and the site is staticCloudflare, based on this test
You rely on Next.js server features (SSR, ISR, middleware, `/_next/image`)Vercel: a static export removes these
Your audience is mainly in western EuropeTest first; Vercel was faster in Germany here
Desktop Lighthouse is your main KPINeither clearly; the gap was ~78 ms, close to noise
The site earns money and you're on a free tierRead the terms: Vercel Hobby is non-commercial
You want every setting visible in GitEither, but keep redirects in code, not dashboards

What this does not show

  • One network, one location, one machine. Geography drives much of the gap.
  • No real-user data. These are lab and synthetic numbers.
  • Chrome only. No Safari or Firefox.
  • Cost and behaviour under load were not tested.
  • The Vercel copy runs today's code, not the exact historical deployment.
Roadmap of four steps in a row: real-user data (RUM), then Safari and Firefox, then a second network, ending at the goal, under 1 s continent-wide. Text: the goal is a site that loads in under a second for anyone on the continent; the full write-up, with tables and method, is on kaikhalid.com.
Diagram 7

Get the data

All the raw numbers behind this post are open: 1,200 curl timings, 280 Lighthouse runs and the multi-region check, with the pre-registration and analysis scripts, are at kaikhalid.com/data/benchmark-2026-10-16 under CC BY 4.0. Download the ZIP, check my medians, or rerun the analysis. If you reuse it, please cite: Khalid, K. (2026). Vercel vs Cloudflare TTFB and Lighthouse benchmark from Nairobi [Data set]. https://kaikhalid.com/data/benchmark-2026-10-16.

FAQ

Is Cloudflare faster than Vercel for a Next.js site?

In my test from Kenya, yes for time to first byte (~250 ms faster at the median) and mobile LCP. Vercel was slightly faster on desktop Lighthouse LCP, and faster from parts of western Europe and Hong Kong.

Why was Cloudflare faster from Nairobi?

It served requests from its Nairobi location, while Vercel served from Cape Town. The TLS handshake alone dropped from 200 ms to 21 ms.

Can a Next.js site run on Cloudflare Workers?

A static export can, using Workers static assets. You lose server-side features and Vercel's image optimiser, so you'll need a build-time image step.

What is Cloudflare error 100117?

It appeared when I attached a custom domain to the Worker while an existing A or CNAME record was still on that hostname. Removing the old record fixed it.

Can I use Vercel's free plan for a business site?

Vercel's Hobby plan is for non-commercial personal use. Check the current terms on Vercel's site.

I also posted this as a thread on X

ShareLinkedInXWhatsAppFacebook

Done

Local page

This site keeps a few things in your browser. Functional is always on. Analytics tells me how people use the site, and stays off until you turn it on. Read the Privacy notice.