🚀 Executive Summary

TL;DR: Unexpectedly high Vercel bandwidth costs for Next.js apps often stem from Cloudflare’s initial origin pulls for static assets, effectively billing twice. The core problem is Vercel serving static files to Cloudflare’s edge, incurring charges before Cloudflare caches them. Solutions involve strategic Cloudflare caching via Page Rules or, more robustly, offloading static assets entirely to Cloudflare R2 to bypass Vercel’s bandwidth meter for these resources.

🎯 Key Takeaways

  • Vercel charges for bandwidth when Cloudflare performs an ‘origin pull’ for static assets, even if Cloudflare subsequently caches them, leading to potential double billing for initial requests.
  • Implementing a Cloudflare Page Rule to ‘Cache Everything’ for `_next/*` paths can significantly reduce Vercel bandwidth, but critically requires a CI/CD step to purge the Cloudflare cache on every deployment to prevent broken sites.
  • The most effective architectural solution is to offload Next.js static assets to Cloudflare R2 by configuring `assetPrefix` in `next.config.js` and syncing the `_next/static` folder to R2 during the build process, completely bypassing Vercel for static asset delivery.

Can I VINEXT on cloudflare to save money on vercel?

Tired of surprise Vercel bills for your Next.js app? Learn how to strategically use Cloudflare’s caching to slash your Vercel bandwidth costs without a painful migration.

Can I ‘Just’ Use Cloudflare to Save Money on Vercel? A Senior Engineer’s Guide to Slashing Next.js Costs

I remember the Slack message from our Head of Finance. It was just a screenshot of our latest Vercel bill with a single question mark. A junior engineer on the marketing team had spun up a simple Next.js image gallery for a new campaign. It was beautiful, fast, and did exactly what it was supposed to do. A little too well, in fact. It got picked up by a big subreddit, traffic went through the roof, and so did our bandwidth consumption. The bill was 10x what we expected. He’d done everything “right” according to the docs, but he’d missed the one critical detail that separates a smooth launch from a budget-busting fire drill: understanding where your bytes are actually coming from, and who is charging you for them.

The “Why”: Paying for Bandwidth Twice

Let’s get one thing straight: I love Vercel. The developer experience is second to none for deploying a Next.js application. You `git push` and it just works. But that magic comes with a specific billing model, and a key part of that is bandwidth. Vercel charges you for the data that leaves their servers and goes to the user.

The common misconception I see is thinking, “I’ll just put Cloudflare in front of Vercel! Problem solved.” Not so fast. When a user requests an image or a JavaScript file from your site for the first time, this is what happens:

  1. The user’s browser asks Cloudflare for `_next/static/chunks/app-123abc.js`.
  2. Cloudflare doesn’t have it cached yet, so it turns around and asks your Vercel deployment for the same file.
  3. Vercel serves the file to Cloudflare. This is the moment you get billed by Vercel for bandwidth.
  4. Cloudflare saves a copy of the file to its edge cache and then serves it to the user.

For every subsequent user in that same region, Cloudflare serves the file from its cache, and Vercel is never touched. That’s great, but you still paid Vercel for that initial “origin pull” for every single static asset, in every single Cloudflare data center that requested it. If your assets are large or your traffic is global, this adds up incredibly fast. You’re not trying to replace Vercel’s CDN; you’re trying to prevent Vercel from being the origin for your heavy static assets.

The Fixes: From a Band-Aid to Major Surgery

Depending on your budget, timeline, and risk tolerance, you have a few options. I’ve used all three in different scenarios, from hotfixes on a staging environment to re-architecting our primary production workloads.

Solution 1: The Quick & Dirty Page Rule (The ‘VINEXT’ Method)

This is the fastest way to get some relief and is likely what the original Reddit poster was thinking of. You’re telling Cloudflare to be extremely aggressive about caching everything under your `_next/static` path, which is where all of Next.js’s compiled and hashed assets live.

How to do it:

  1. Go to your domain in the Cloudflare dashboard.
  2. Navigate to “Rules” -> “Page Rules”.
  3. Create a new rule with the following settings:
    • URL: *yourdomain.com/_next/*
    • Setting: Cache Level
    • Value: Cache Everything
  4. Add another setting:
    • Setting: Edge Cache TTL
    • Value: a month (or your desired duration)

This tells Cloudflare to ignore whatever caching headers Vercel sends for those assets and just hold onto them for a month. It dramatically reduces the number of times Cloudflare has to go back to Vercel for the same file.

Warning from the Trenches: If you use this method, you MUST set up a step in your CI/CD pipeline to purge the Cloudflare cache on every single deployment. The command is `POST zones/:zone_id/purge_cache`. If you don’t, your users will get new HTML from Vercel pointing to old, cached JavaScript and CSS assets, and your site will break in very confusing ways. Ask me how I know.

Solution 2: The Proper Architecture (Offloading to R2)

This is my preferred method for any serious project. The goal here is to stop Vercel from ever serving the static assets in the first place. We’ll use Cloudflare R2, which has a very generous free tier and zero egress fees, making it perfect for this job.

How to do it:

  1. Create an R2 Bucket: In Cloudflare, create a new R2 bucket (e.g., `my-app-static-assets`). Connect a public domain to it, like `static.yourdomain.com`.
  2. Update Your Next.js Config: Tell Next.js to look for its static assets at this new domain.
    
    // next.config.js
    const isProd = process.env.NODE_ENV === 'production'
    
    module.exports = {
      // Use the R2 bucket URL in production
      assetPrefix: isProd ? 'https://static.yourdomain.com' : '',
    }
    
  3. Modify Your Build Step: In your CI/CD pipeline (e.g., GitHub Actions), after you run `next build`, you need to sync the contents of the generated static folder to your R2 bucket. Using the `wrangler` CLI is perfect for this.
    
    # In your deploy script, after `npx next build`
    npx wrangler r2 object put my-app-static-assets/.next/static .next/static --recursive
    

Now, Vercel is only responsible for Server-Side Rendering (SSR), API routes, and serving the initial HTML. All the heavy lifting for JS, CSS, and images is done by Cloudflare R2, completely bypassing Vercel’s bandwidth meter.

Solution 3: The ‘Nuclear’ Option (Self-Hosting with OpenNext)

Sometimes, you just outgrow the platform. If you need absolute control over every dial of your infrastructure and cost, or if Vercel’s function limits and execution times are holding you back, it might be time to leave the nest. This is not a decision to take lightly.

What is it? OpenNext is a fantastic open-source project that takes your Next.js build output and converts it into a package that can be deployed on AWS using native services like Lambda, S3, and CloudFront. You are effectively building your own Vercel.

Why do it? You get granular control over costs. You can set fine-grained AWS Budgets, leverage AWS Free Tier, and tune every aspect of the infrastructure. The downside? You are now responsible for the infrastructure. The CI/CD pipeline, the IAM permissions, the monitoring, the logging, the security… it’s all on your team now. You’ve traded the Vercel developer experience for ultimate control.

Comparing The Options

Solution Cost Savings Implementation Effort Maintenance Overhead
1. Page Rule Medium Low (5 minutes) Low (but critical cache purge step)
2. Offload to R2 High Medium (Requires CI/CD changes) Low (Set it and forget it)
3. Self-Host (OpenNext) Potentially Highest Very High (Full infra setup) High (You own everything)

My Final Take

So, can you just put Cloudflare in front of Vercel to save money? Yes, but you have to do it thoughtfully. For a small project or a quick fix, the Page Rule method (Solution 1) is a perfectly valid way to stop the bleeding. For any new, serious project, I strongly advocate for starting with the R2 Offloading architecture (Solution 2). It’s the best of both worlds: you keep the incredible Vercel DX for your application code while treating your static assets like the commodities they are, served from the cheapest and fastest location.

Reserve the Nuclear Option (Solution 3) for when your scale and requirements truly demand it. Moving off a managed platform is a major engineering investment, not just a cost-saving exercise. Choose wisely, and keep an eye on those billing dashboards.

Darian Vance - Lead Cloud Architect

Darian Vance

Lead Cloud Architect & DevOps Strategist

With over 12 years in system architecture and automation, Darian specializes in simplifying complex cloud infrastructures. An advocate for open-source solutions, he founded TechResolve to provide engineers with actionable, battle-tested troubleshooting guides and robust software alternatives.


🤖 Frequently Asked Questions

âť“ How does Cloudflare interact with Vercel’s billing for Next.js static assets?

When Cloudflare doesn’t have an asset cached, it requests it from Vercel (an ‘origin pull’). Vercel bills for the bandwidth used to serve this file to Cloudflare’s edge, even though Cloudflare then caches and serves it to the end-user.

âť“ How do Cloudflare Page Rules compare to offloading static assets to R2 for cost savings?

Page Rules offer medium cost savings with low implementation effort, aggressively caching `_next/static` but requiring manual cache purging. Offloading to R2 provides high cost savings and is a more robust architectural solution, completely bypassing Vercel for static assets, with medium implementation effort and low maintenance.

âť“ What is a common implementation pitfall when using Cloudflare Page Rules for Next.js assets on Vercel?

The critical pitfall is failing to purge the Cloudflare cache on every deployment. This results in users receiving new HTML from Vercel that references old, cached JavaScript and CSS assets, leading to broken site functionality.

Leave a Reply

Discover more from TechResolve - SaaS Troubleshooting & Software Alternatives

Subscribe now to keep reading and get access to the full archive.

Continue reading