301 Redirects: Cloudflare Pages vs Vercel vs Netlify vs Render vs GitHub Pages
How 301 redirects work on Cloudflare Pages, Vercel, Netlify, Render, and GitHub Pages. Config examples and limits compared.

The short answer: Every static hosting platform handles 301 redirects differently. Netlify and Cloudflare Pages both support the _redirects file. Vercel uses vercel.json with regex support. Render only offers dashboard configuration. GitHub Pages cannot do server-side redirects at all.
Moving or renaming pages without proper redirects is one of the fastest ways to lose search rankings. When Google finds a 404 instead of a redirect, the link equity that page earned over months disappears. Here is exactly how each of the five major static hosting platforms handles 301 redirects, with config examples and limits.
Cloudflare Pages
Cloudflare Pages uses a plain-text _redirects file placed in your build output directory (usually public/). Each line defines one rule.
/old-page /new-page 301
/blog/old /blog/new 301
/docs/* /reference/:splat 301Cloudflare supports status codes 301, 302, 303, 307, and 308. The default is 302 if you omit the code. Splats (*) match any string from that point forward, and you reference the captured value with :splat in the destination. Named placeholders like :id are also supported.
Limits: 2,000 static redirects plus 100 dynamic redirects (those using splats or placeholders), for a total of 2,100. Each rule has a 1,000-character limit. For projects that need more, Cloudflare offers Bulk Redirects as a separate product that runs before the _redirects file.
Gotchas: Query parameters are not supported in redirect rules. Redirects do not apply to requests handled by Pages Functions. The topmost matching rule wins.
If you are planning a URL restructure, get a free audit so we can map every redirect you need before traffic drops.
Netlify
Netlify supports two config methods: the `redirects` file (which Netlify invented) and the `netlify.toml` file. Rules from `redirects are processed first, followed by netlify.toml` rules.
Using `_redirects`:
/old-page /new-page 301
/blog/* /news/:splat 301!The ! suffix forces the redirect even when a file exists at that path.
Using `netlify.toml`:
[[redirects]]
from = "/old-page"
to = "/new-page"
status = 301Netlify's default status code is 301 (unlike Cloudflare's 302 default). It supports splats, named placeholders, query string matching, country and language conditions, cookie-based conditions, and forced redirects. The netlify.toml format adds signed proxy redirects and custom headers.
Limits: Netlify recommends staying under 10,000 redirect rules. Beyond that, deployment may fail if the serialized output is too large. For complex routing at scale, Netlify suggests Edge Functions instead.
Gotchas: Files starting with `` can be excluded by static site generators like Jekyll. Edge Functions run before redirect rules, so edge logic can override your `redirects` file.
Vercel
Vercel uses vercel.json (or the newer vercel.ts for dynamic config) in your project root. Redirects are defined as an array of objects.
{
"redirects": [
{ "source": "/old-page", "destination": "/new-page", "permanent": true },
{ "source": "/blog/:slug", "destination": "/news/:slug", "permanent": true }
]
}Setting permanent: true returns a 308 status code. Setting permanent: false returns 307. If you specifically need a 301 or 302, use the statusCode field instead of permanent.
Vercel supports full regex in the source field, named path segments (:slug), and wildcard matching (:path*). It also supports conditional redirects with has and missing properties, letting you redirect based on headers, cookies, query strings, or host values.
Bulk redirects: For large-scale migrations, Vercel offers bulkRedirectsPath which points to a CSV, JSON, or JSONL file containing thousands of redirect rules. These do not support wildcards or conditional matching.
Gotchas: The has conditional property does not work locally with vercel dev, only in deployed environments. The default permanent value is true (308), which differs from most other platforms.
Not sure which redirect approach fits your site? We can run a free check and show you what to fix.
Render
Render configures redirects exclusively through its dashboard UI. There is no file-based configuration.
In the dashboard, you define rules with a source path, destination path (or full URL), and choose between "Redirect" (301) or "Rewrite" (serves content without changing the URL).
Source: /old-page
Destination: /new-page
Action: Redirect (301)Render supports wildcards (*) in the source, and the captured value carries over to the destination. Named placeholders like :postid also work.
Limits: Render only supports 301 for redirects. There is no option for 302, 307, or 308 status codes.
Gotchas: You cannot redirect the domain root (/). Each source must have at least one URL path component. If a static file exists at the source path, Render serves the file instead of applying the redirect rule. This means redirects only work for paths where no asset exists.
GitHub Pages
GitHub Pages has no server-side redirect support. There is no _redirects file, no config file, and no dashboard option. The only workaround is placing an HTML file at the old path with a client-side redirect:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=/new-page">
<link rel="canonical" href="/new-page">
</head>
<body>
<script>window.location.replace("/new-page")</script>
</body>
</html>This approach has real problems for [SEO](/services/indexing-monitoring). The meta refresh tag sends a 200 status code, not a 301. Search engines may treat it as a temporary redirect or ignore it entirely. The canonical tag helps, but it is a hint, not a directive. Google may or may not follow it.
For a handful of pages this workaround is acceptable. For a site migration with dozens of URL changes, it is not reliable enough to preserve rankings.
Side-by-Side Comparison
| Feature | Cloudflare Pages | Netlify | Vercel | Render | GitHub Pages |
|---|---|---|---|---|---|
| Config method | `_redirects` file | `_redirects` or `netlify.toml` | `vercel.json` or `vercel.ts` | Dashboard UI | None (HTML workaround) |
| True 301 support | Yes | Yes | Yes (via `statusCode`) | Yes (only 301) | No |
| Default status code | 302 | 301 | 308 | 301 | N/A |
| Other status codes | 301, 303, 307, 308 | All standard codes | 301, 302, 303, 307, 308 | None | N/A |
| Wildcards/splats | Yes | Yes | Yes (regex too) | Yes | N/A |
| Named placeholders | Yes | Yes | Yes | Yes | N/A |
| Conditional redirects | No | Country, language, cookies | Headers, cookies, query strings | No | N/A |
| Query string matching | No | Yes | Yes (via `has`) | No | N/A |
| Redirect limit | 2,100 | ~10,000 recommended | No published limit | No published limit | N/A |
| Bulk redirect option | Yes (Bulk Redirects) | Edge Functions | CSV/JSON/JSONL file | No | N/A |
| Force over existing file | No | Yes (`!` flag) | N/A (no conflict) | No (file wins) | N/A |
| Free tier bandwidth | Unlimited | 100 GB/mo | 100 GB/mo | 100 GB/mo | 100 GB/mo |
- Cloudflare Pages and Netlify both support the
_redirectsfile, but their defaults differ (302 vs 301) - Vercel has the most powerful matching with full regex and conditional redirects based on headers and cookies
- Render is the simplest option but is also the most limited (dashboard only, 301 only, no root redirects)
- GitHub Pages is the only platform with zero server-side redirect support
- For SEO-critical site migrations, avoid GitHub Pages and Render's limitations
A hosting platform that makes redirects easy can save your rankings during every site update. If your current host requires workarounds for something as basic as a 301 redirect, it may be time to reconsider.