Vercel vs Cloudflare Pages Redirect Loops

Cloudflare Vercel redirects

You move a site from Vercel to Cloudflare Pages (or put Cloudflare in front of Vercel). Browser shows ERR_TOO_MANY_REDIRECTS. curl shows a 301 ping-pong between https://example.com and https://www.example.com, or between HTTP and HTTPS. Each platform’s “force HTTPS” / “www redirect” is correct in isolation. Together they form a loop. Clearing cookies does not fix a policy collision.

Classic loop topologies

Apex ↔ www disagreement. Cloudflare Redirect Rule sends apex → www. Vercel domain settings send www → apex. Endless 301.

HTTP ↔ HTTPS double enforcement. Origin redirects HTTP→HTTPS with an absolute Location to host A. Edge also redirects but rewrites host to B. Scheme or host flip-flops.

Trailing slash wars. Framework redirects /foo/foo/. CDN rule redirects /foo//foo.

Duplicate config. Old vercel.json redirects still deployed while Cloudflare Bulk Redirects encode the opposite target. Preview host rules accidentally applied globally.

Debug with curl, not the browser

Browsers cache redirects aggressively. Map hops explicitly:

curl -sI https://example.com | egrep -i 'HTTP/|location|cf-|server|x-vercel'
curl -sI https://www.example.com | egrep -i 'HTTP/|location|cf-|server|x-vercel'
curl -sI http://example.com | egrep -i 'HTTP/|location'

List each Location on paper. Note which hop adds cf-ray versus x-vercel-id — that tells you who issued the redirect. A healthy cutover shows zero or one hop to the canonical URL.

One canonical host, one owner

Pick exactly one canonical: https://example.com or https://www.example.com. Then:

  1. DNS resolves both names appropriately (proxied or not — know which).
  2. A single 301 from the non-canonical host to the canonical.
  3. HTTPS termination consistent end-to-end.
SetupRecommendation
Cloudflare proxy → Vercel originHost redirects at Cloudflare; disable opposing Vercel www/apex redirects
Cloudflare Pages onlyOne of: _redirects, Bulk Redirects, or Wrangler — not three copies
Vercel onlyDomain panel + vercel.json — no opposite registrar/CDN rules

Flexible SSL is a famous footgun

Cloudflare SSL mode Flexible talks HTTP to the origin. If the origin forces HTTPS redirects to the public hostname, edge and origin bounce forever. Use Full (strict) with a valid origin certificate (or Cloudflare Origin CA) when the orange cloud is on. Flexible + “Always Use HTTPS” + origin HTTPS redirect is the incident report you already wrote last year.

Inventory every redirect source

During migration, list and disable until one remains:

  1. Cloudflare Redirect Rules, legacy Page Rules, Bulk Redirects, Transform Rules, Workers returning Response.redirect
  2. Vercel project Domains, vercel.json redirects/rewrites, Next middleware redirects
  3. Framework trailing-slash / basePath settings
  4. DNS-only vs proxied — DNS-only bypasses Cloudflare redirect features

Delete or disable the old platform’s host redirects before enabling the new ones when possible. Path-level marketing redirects can wait until the host is stable.

Incident fix sequence

  1. If proxied, set SSL to Full (strict).
  2. Disable www/apex redirects on one side entirely.
  3. Confirm curl hop list length is 0–1.
  4. Re-enable a single documented host redirect.
  5. Purge CDN cache; verify in a private window.
  6. Only then restore path-level redirects.

Trailing slash and case

trailingSlash: true in Next/Astro must match CDN rewrites. Auth gateways that normalize case can also bounce. Treat slash policy as part of the same “one owner” rule.

Redirect loops are almost never “DNS propagation” and almost never “clear cookies.” They are two owners of Location headers disagreeing. Make one owner, verify with curl -I, keep the other platform passive on host canonicalization.