Cloudflare Pages vs Netlify: Free Limits, Redirects, Caching
Compare Cloudflare Pages and Netlify for a static marketing site using documented limits, 500 builds versus 300 credits, redirect rules, caching and analytics.
Cloudflare Pages and Netlify both deploy a static site from a Git repository in minutes, so the useful comparison is what each one meters, what its _redirects file accepts, how it invalidates the cache after a deploy, and what analytics you get without paying. Those four things decide the bill and the migration effort for a small marketing site; the ten-minute setup does not.
Correction, September 25, 2026: an earlier version of this article described a client site moved from Netlify to Cloudflare Pages, with a $19 build-minute overage, three of fourteen redirects failing and a two-hour caching problem. Those were not documented events and have been removed. This version uses the vendors’ published limits and explicitly hypothetical arithmetic. It also reflects that Netlify replaced build-minute metering with credits for accounts created from September 4, 2025.
Illustration only; the meters are not a measurement of either service.
What the free tiers actually meter
The table reads from official documentation checked on September 25, 2026. Netlify’s numbers are for its credit-based plans, which apply to every account created on or after September 4, 2025; older accounts stay on legacy plans that did meter build minutes, so check which plan your own team is on before using this table.
| What is metered | Cloudflare Pages, Free | Netlify, Free (credit-based) | Sources |
|---|---|---|---|
| Deploys or builds | 500 builds per month, 1 build at a time, 20-minute build timeout | 300 credits per month; each production deploy costs 15 credits (20 deploys if nothing else is used). Deploy Previews and branch deploys have no deployment charge; their traffic still uses credits | Pages limits, How credits work |
| Build minutes | Not metered; the limit is builds, not minutes | “Build minutes are not calculated as their own metric” on credit plans; extra concurrent builds are a $40 add-on on paid plans | Pages limits, Billing FAQ |
| Bandwidth | “No additional charges for data transfer (egress) or throughput (bandwidth)”; static asset requests “free and unlimited” | 20 credits per GB served | Workers pricing, How credits work |
| Requests | Free for static assets | 2 credits per 10,000 web requests | same |
| Site size | 20,000 files, 25 MiB per file | Not stated on the pages checked | Pages limits |
| When the limit is hit | Builds fail until the next month; the live site keeps serving | Free plan is a hard limit with no auto-recharge: “all of your web projects are paused and visitors … will find a Site not available page” | Pages limits, Credit-based plans |
| First paid step | Workers Paid starts at $5 per month for Functions usage; Pages Pro raises builds to 5,000 (a different limit) | Personal $9 for 1,000 credits; Pro $20 for 3,000 credits, unlimited seats; auto-recharge 500 credits for $5 (Personal) or 1,500 for $10 (Pro) | Workers pricing, Credit-based plans |
Two things in that table matter more than the headline prices. First, Netlify’s free tier meters traffic, not just deploys, and the consequence of running out is the site going offline rather than a failed build. Second, Cloudflare does not meter bandwidth on either the free or the paid plan, which removes the metric a marketing site is least able to predict. Neither point says one service is cheaper for you; it says which service’s bill depends on things you control.
A hypothetical month, with the arithmetic shown
Netlify credit rates and billing scope rechecked October 13, 2026 against How credits work. Other table entries retain their September 25 check date.
Suppose a team hosts just one static marketing site and publishes three times a week. The inputs below include production and preview traffic and assume no compute, database or AI usage. They are hypothetical, not measurements of this site.
- Production deploys: 12 in the month. On Netlify that is 12 × 15 = 180 credits. On Cloudflare Pages that is 12 of 500 builds.
- Bandwidth: 4 GB served. Netlify: 4 × 20 = 80 credits. Cloudflare: not metered.
- Requests: 100,000. Netlify: (100,000 ÷ 10,000) × 2 = 20 credits. Cloudflare: not metered for static assets.
- Netlify total: 180 + 80 + 20 = 280 of 300 credits. One more production deploy (15 credits) fits; a second does not, and on the Free plan the site pauses when the balance reaches zero.
Change the inputs and the answer changes. A site deploying once a week with the same traffic uses 4 × 15 + 80 + 20 = 160 credits and never approaches the limit. A site that deploys on every content edit, twenty times a month, spends 300 credits on deploys alone before serving a byte. Only successful production deployments incur the 15-credit deployment charge; failed deploys and rollbacks do not. A successful “publish, spot a typo, publish again” therefore uses 30 deployment credits. Preview deployment itself is free, but requests to previews and branch deploys still count. Do not substitute analytics pageviews for billed requests: assets and redirects count too. The shared team balance also covers other projects, so this example is not a separate allowance for each site.
The practical rule is to count your production deploys for one real month before choosing, the same way a pricing audit counts what a plan actually meters rather than what the marketing page leads with. If you already have a Netlify legacy account, its build-minute allotment is a different calculation and the credit arithmetic above does not apply to it.
Redirects: the same file name, a different rule set
Both services read a _redirects file from the build output, but matching syntax does not guarantee matching behaviour. Check conditions, existing files and Function routes before copying rules between hosts. Cloudflare documents that malformed redirect lines are ignored.
| Rule type | Netlify | Cloudflare Pages | Sources |
|---|---|---|---|
Splat * |
Supported; not as a wildcard in the middle of a path (/jobs/*.html) |
Supported; one splat per URL, greedy match | Netlify redirect options, Pages redirects |
Placeholders :slug |
Supported | Supported | same |
| Query-parameter matching | Supported | Not supported | same |
| Country or language conditions | Supported (ISO country codes, browser language codes) | Not supported | same |
| Cookie or role conditions | Supported (roles need Netlify Identity or a JWT provider) | Not supported | same |
| Proxy / rewrite with status 200 | Supported, including external URLs | Only relative URLs on your own site; external proxying not supported | same |
| Default status when omitted | 301 | 302 | same |
| Documented rule limits | None stated on the redirect-options page | 2,000 static + 100 dynamic rules (2,100 total), 1,000 characters per line; Cloudflare points to Bulk Redirects beyond that | same |
Two rows deserve attention when migrating URL history. The default status differs, so a file written for Netlify without explicit codes becomes a set of temporary redirects on Cloudflare; add 301 to every permanent rule before moving. And any rule that depends on a query string, a country or a cookie has no Cloudflare equivalent in _redirects; those need a Pages Function or a Cloudflare Rules feature, which is separate work to scope before the migration date, not after. The old version of this article described that work as “an afternoon”; the honest answer is that it depends on how many conditional rules you have, which is why the worksheet below asks you to count them.
Existing files and Function routes change the result
Checked October 13, 2026 against Netlify redirect options and Cloudflare Pages redirects. This check covers routing behaviour, not the pricing or analytics figures elsewhere in this article.
| Request situation | Netlify | Cloudflare Pages |
|---|---|---|
| A file exists at the source path | The file can prevent the redirect; append ! to the status code to force it |
A matching redirect takes priority over an existing static asset |
| A Pages Function handles the source URL | Check the Netlify route separately; this is a Pages-specific boundary | _redirects does not apply; implement the redirect in the Function or exclude that route from Functions |
For a hypothetical migration, suppose /old.html still exists and the rule is /old.html /new.html 301. Netlify can serve the old file; Pages redirects the static request. On Netlify, 301! forces the redirect. Do not assume copying that suffix to another host is necessary or supported.
Before switching DNS, request one existing-file path, one missing-file path and any Function-handled path on the preview. Record the initial status and Location header, then follow the destination and check its content. A successful build alone cannot establish that the routing matches your intent. These are suggested acceptance checks, not results of a migration tested for this article.
Whichever direction you move, test every rule against the deployed preview. An ineffective rule can leave an old page visible or produce a 404, and migration work that nobody schedules is usually this kind of check.
Caching: what each vendor documents about stale deploys
Netlify’s caching documentation states that “all new deploys invalidate the cache for the given deploy context by default,” and that this override “guarantees that we never accidentally serve stale content.” A Netlify deploy is atomic and the CDN cache for that context is cleared with it.
Cloudflare Pages documents a similar default for its own layer: each deployed asset “remains cached on the Cloudflare CDN until your next deployment,” served with Cache-Control: public, max-age=0, must-revalidate. The difference is what sits in front of it. If your custom domain is on a Cloudflare zone, that zone’s Cache Rules and Page Rules apply to the Pages site too, and Cloudflare’s guidance is explicit: adding caching to the custom domain “may cause issues with Pages redirects or Pages functions” and “may lead to stale assets being served after a deployment.” The recommended default is to add no custom caching except for hashed, immutable assets.
So the documented risk is not that Cloudflare Pages caches badly; it is that a Cloudflare zone can carry rules that predate the site. Before you diagnose a “deploy succeeded but the page did not change” report as a build problem, check the zone’s Cache Rules and Page Rules for anything that caches HTML. A zone that once hosted a WordPress installation with an aggressive cache-everything rule is the textbook case, but you need to look at your own zone rather than assume it.
Functions and analytics
Functions: a static page can still invoke paid code
Cloudflare runtime and billing scope checked October 14, 2026; Netlify’s function figures below retain their September 25 check date.
| Cloudflare boundary | What to budget or check | Source |
|---|---|---|
| Static delivery | Requests that do not invoke Functions are free and unlimited | Pages Functions pricing |
| Workers Free | 100,000 daily requests shared between Workers and Pages Functions, resetting at midnight UTC; not a separate allowance per site | Pages Functions pricing |
| Workers Paid, Standard | $5 USD monthly account minimum includes 10 million requests and 30 million CPU milliseconds; excess costs $0.30 per million requests and $0.02 per million CPU milliseconds | Workers pricing |
| Function routes | Inspect the generated _routes.json; exclude static routes that should bypass Functions |
Invocation routes |
A hypothetical image request that passes through a Function is not free static delivery merely because the response is an image. Check middleware and route exclusions before assuming the static-only budget applies. On Free, exhausted Function allowance can either serve static assets without running the Function (fail open) or return an error (fail closed). If a Function protects private content, choose this behaviour deliberately; bypassing authentication is not a suitable fallback.
Pages Functions use the Workers runtime, not a full Node.js server. The Node compatibility guide enables compatibility by default for dates from August 4, 2026, but distinguishes supported APIs from import-only stubs. A successful package import does not prove its methods work. Before migrating, exercise the actual form submission, database call and error path on a preview using the project’s compatibility date. These are proposed checks, not tests performed for this article.
Netlify Functions default to 1,024 MB of memory and, on credit plans, are billed as compute at 10 credits per GB-hour. For either host, estimate function invocations and compute separately from static traffic; a contact form’s cost depends on usage and implementation, not its label.
Analytics. Cloudflare Web Analytics is free on all plans, is enabled from the Pages project’s Metrics tab with a snippet Cloudflare injects on the next deploy, and Cloudflare states it uses no cookies or localStorage and does not fingerprint visitors by IP or User Agent. Netlify’s Web Analytics is included in its credit-based plans, but its official pages disagree on retention. Checked October 13, 2026: the pricing page lists Free/Personal/Pro as 1/7/30 days, while the billing documentation says current/past day, 24 hours and 30 days. Confirm the window available to your account before paying specifically for Personal analytics history. Netlify also offers an add-on level priced by pageviews, and legacy accounts that move to credit plans have any existing Analytics subscription “terminated immediately” without refund. The earlier version of this article treated Netlify Analytics as a flat $9 a month per site; that figure belongs to the legacy plans and should not be assumed for a new account.
Whether either built-in tool is enough is a separate question from cost. Both report pageviews and top pages; neither replaces a full analytics product, and a site that needs event tracking will end up evaluating what the export of a tool actually contains before trusting either as the system of record.
One more thing to know about Cloudflare Pages
Cloudflare now positions Workers with static assets as the broader platform. Its migration guide, last updated September 22, 2026, says Workers “has a distinctly broader set of features,” while Pages retains some things Workers does not: custom domains outside Cloudflare zones, branch deploy controls, custom branch aliases and file-based routing. The guide does not deprecate Pages or set an end date. For a marketing site the practical reading is that Pages still does everything this article compares, and a team starting today should at least read that compatibility matrix before choosing, because the two Cloudflare products do not have identical _redirects and domain behaviour.
Which service, for a marketing site
- Choose Cloudflare Pages when your production deploy count is unpredictable, traffic could spike, or your domain is already on a Cloudflare zone and you can audit its cache rules. Static requests that bypass Functions are free; Function requests have a shared daily allowance.
- Choose Netlify when you depend on conditional redirects (country, language, query string, cookie), external proxying, or role-based access, or when your team wants cache invalidation with no zone configuration to inspect. Budget the credits: count production deploys and estimate monthly gigabytes first.
- Do not decide on the ten-minute setup. Both pass that test. Decide on the metered items you cannot control and on the redirect rows above that your existing URL history needs.
- Do not decide on the annual price either. Netlify’s Pro tiers and Cloudflare’s paid plan are monthly; if a vendor offers a discount for prepaying, treat it the way an annual discount deserves to be treated, after the monthly usage is known.
Worksheet: fill this before migrating in either direction
| Question | Your number | Cloudflare Pages consequence | Netlify consequence |
|---|---|---|---|
| Production deploys per month (from Git history, last 3 months) | Compare with 500 | × 15 credits | |
| Bandwidth per month, GB (from current host’s dashboard) | Not metered | × 20 credits | |
| Requests per month (production + previews, including assets) | Not metered for static assets | ÷ 10,000 × 2 credits | |
| Redirect rules by type | At most 2,000 static and 100 dynamic in _redirects; the limits are separate |
No documented limit on the page checked | |
| Rules using query string, country, language, cookie or role | Each needs a Function or a Rules feature | Supported in _redirects |
|
| Rules proxying an external domain | Not supported in _redirects |
Supported | |
| Source paths with existing files or Pages Functions | Static redirects override files; Function-handled requests bypass _redirects |
Check file shadowing and whether forcing is intended | |
| Rules without an explicit status code | Become 302 | Become 301 | |
| Zone cache rules that touch HTML (Cloudflare zones only) | Audit or remove before launch | Not applicable | |
| Functions using Node-only modules | Check the Node compatibility list | Check memory and GB-hour cost | |
| Analytics lookback you need | Web Analytics, free | Official pages disagree for Free/Personal; verify in account (Pro: 30 days) |
An illustrative row: a site with 12 deploys, 4 GB, 100,000 requests and 14 redirect rules, two of which are country-based, scores 280 Netlify credits and needs two Cloudflare Functions. That covers the static budget and redirect scope; any Function invocations and CPU usage need a separate estimate.
Checklist
- Confirm which Netlify plan family your account is on (legacy or credit-based) before using any credit figure.
- Count production deploys for one real month; count only successful production deployments in that meter; include preview traffic in usage.
- Pull bandwidth and request counts from the current host before estimating credits.
- Export the full
_redirectsfile and tag each rule by type using the table above. - Add explicit
301to permanent rules before moving to Cloudflare. - On a Cloudflare zone, list every Cache Rule and Page Rule and confirm none caches HTML.
- Test every redirect against the preview deployment and record the result.
- Enable analytics on the new host on day one so there is a baseline, and keep the old host live until the redirect test is complete. A reversible move is one where the previous host still answers while you check.
Sources (checked September 25, 2026)
- Cloudflare, Pages limits: builds per plan, concurrency, file limits,
_redirectslimits. - Cloudflare, Pages redirects: supported syntax, default 302, unsupported features.
- Cloudflare, Serving Pages: default cache headers, cache until next deployment, warning about custom-domain caching.
- Cloudflare, Workers pricing: free and paid limits, no bandwidth charges, Pages Functions billed as Workers.
- Cloudflare, Node.js compatibility: default from compatibility date 2026-08-04, stub modules.
- Cloudflare, Web Analytics product page and Web Analytics for Pages: free, no cookies, no fingerprinting, one-click enable.
- Cloudflare, Migrate from Pages to Workers: compatibility matrix, last updated September 22, 2026.
- Netlify, How credits work: credit costs per deploy, GB, requests and GB-hour; Free plan pause.
- Netlify, Credit-based pricing plans: plan prices, tiers, analytics lookback, add-ons.
- Netlify, Billing FAQ for credit-based plans: September 4, 2025 cutover, build minutes not metered, legacy Analytics termination.
- Netlify, Redirect options: splats, placeholders, query, country, language, cookie and role rules, default 301.
- Netlify, Caching: deploy-based invalidation, default headers.
- Netlify, Functions usage and billing: default memory, GB-hour credits.



