Cloudflare Vercel Workflow: Deploying NextJS with Edge Caching
Cloudflare Vercel Workflow: Deploying NextJS with Edge Caching
Next.js, Vercel, and Cloudflare together form a powerful stack for building high‑performance web applications. Vercel gives you a zero‑config deployment platform with native Next.js support, while Cloudflare’s global network and edge caching turbocharge delivery, reduce latency, and help your app scale smoothly under traffic spikes.
Why Combine Vercel and Cloudflare?
Even though Vercel already has a global edge network, you may still want Cloudflare in front for several reasons:
- Unified DNS and security: Keep all your domains, SSL, and DNS management in Cloudflare.
- Extra caching layer: Offload traffic to Cloudflare’s edge cache and reduce hits to Vercel.
- Web Application Firewall (WAF): Add security rules and bot protection without touching your Vercel config.
- Analytics and observability: Use Cloudflare analytics alongside Vercel’s to better understand traffic and caching behavior.
- Zero‑downtime domain migrations: Gradually shift traffic between platforms using Cloudflare’s DNS and proxying.
High-Level Architecture
The typical workflow looks like this:
- User requests
https://your-domain.com. - DNS for
your-domain.comis managed by Cloudflare. - Cloudflare sits as a reverse proxy in front of Vercel.
- Cloudflare either:
- Serves the response from its edge cache, or
- Forwards the request to your Vercel project.
- Vercel runs your Next.js app (including any SSR, ISR, or Edge Functions logic).
- Cloudflare caches allowed responses and sends the result back to the user.
Step 1: Prepare Your Next.js App
Start with a standard Next.js project. If you don’t already have one:
npx create-next-app@latest my-app
cd my-app
npm run dev
Make sure it runs locally on http://localhost:3000 before proceeding.
Use Edge Runtime Where It Makes Sense
If you want some logic to run as close to your users as possible, Next.js Edge Runtime is ideal. For example, a middleware that runs on the edge:
// middleware.ts (or middleware.js)
import { NextResponse } from 'next/server';
export const config = {
matcher: ['/dashboard/:path*'],
};
export function middleware(request: Request) {
const { pathname } = new URL(request.url);
// Simple A/B test or feature flag at the edge
if (pathname.startsWith('/dashboard')) {
return NextResponse.next({
headers: {
'x-powered-by': 'nextjs-edge',
},
});
}
return NextResponse.next();
}
Vercel will deploy this as an Edge Function, giving you very low latency decision‑making for every request that matches the path.
Step 2: Deploy Next.js to Vercel
- Push your code to GitHub, GitLab, or Bitbucket.
- Go to Vercel and import your repository.
-
Vercel will auto‑detect Next.js and pick sensible defaults. If you have environment variables, add them under:
Project Settings > Environment Variables. -
Trigger a deployment. Once finished, you’ll get a Vercel URL like:
https://my-app.vercel.app
Visit that URL and verify all pages, API routes, and any dynamic or edge features work correctly. This is your origin that Cloudflare will proxy to.
Step 3: Point Your Domain to Vercel via Cloudflare
3.1 Set Up DNS in Cloudflare
- Ensure your domain’s nameservers point to Cloudflare (through your registrar).
- In the Cloudflare dashboard, open your domain and go to the DNS tab.
- Add a CNAME record for your root or subdomain:
- Name:
@(orwwwif usingwww.your-domain.com) - Target:
cname.vercel-dns.com(Vercel’s recommended target) - Proxy status: Proxied (orange cloud) to put Cloudflare in front.
- Name:
In Vercel, under Project Settings > Domains, add your custom domain (e.g., your-domain.com). Vercel will confirm DNS automatically if your Cloudflare record is correct.
3.2 SSL/TLS Settings
In Cloudflare, go to SSL/TLS:
- Set SSL/TLS encryption mode to Full (or Full (strict) if you have a valid cert at the origin). Vercel manages certificates for its domains, so Full usually works well.
- Enable Always Use HTTPS to force HTTPS at the edge.
Step 4: Configure Caching with Cloudflare
To optimize caching with Next.js and Vercel, set clear rules between:
- What Cloudflare can cache: Mostly static content and some HTML where allowed.
- What Vercel controls: Dynamic/SSR responses, incremental static regeneration (ISR), authentication pages, APIs.
4.1 Understand Next.js Caching Headers
Next.js and Vercel emit helpful Cache-Control headers by default:
- Static assets (e.g.,
/_next/static/*) are typically immutable with long TTLs. - ISR pages might have headers like
s-maxage=<seconds>andstale-while-revalidate. - Dynamic/SSR routes often use
privateor shortmax-ageto avoid over‑caching.
Cloudflare should respect these headers unless you explicitly override them in Page Rules or Cache Rules.
4.2 Create Cache Rules in Cloudflare
In Cloudflare, open Rules > Cache Rules (or Page Rules in older accounts) and define rules similar to:
-
Static Assets: Aggressive Caching
- Rule: If URL path matches
*/_next/static/*or other static directories like/public - Action: Cache everything, respect existing headers, and set a high TTL.
- Rule: If URL path matches
-
HTML/SSR Pages: Respect Origin
- Rule: If URL path is
*(default fallback) - Action: Cache eligible content but honor
Cache-Controlfrom Vercel.
- Rule: If URL path is
-
APIs and Auth: Bypass Cache
- Rule: If URL path matches
*/api/*or*/login,*/callback, etc. - Action: Bypass cache to avoid storing private responses.
- Rule: If URL path matches
Step 5: Edge Caching Strategies with Next.js
5.1 Incremental Static Regeneration (ISR)
ISR lets you serve static pages from the edge while keeping them fresh over time. Example:
// pages/blog/[slug].tsx
import { GetStaticPaths, GetStaticProps } from 'next';
export const getStaticPaths: GetStaticPaths = async () => {
// Pre-render some paths at build time
return {
paths: [{ params: { slug: 'hello-world' } }],
fallback: 'blocking',
};
};
export const getStaticProps: GetStaticProps = async (context) => {
const { slug } = context.params as { slug: string };
// Fetch from your CMS or API
const post = await fetch(`https://api.example.com/posts/${slug}`).then((res) => res.json());
return {
props: { post },
// Regenerate at most once every 60 seconds
revalidate: 60,
};
};
export default function BlogPost({ post }: { post: any }) {
return (
<main>
<h1>{post.title}</h1>
<article dangerouslySetInnerHTML={{ __html: post.content }} />
</main>
);
}
Vercel will serve the static HTML from its edge and re‑generate it in the background when the revalidate window expires. Cloudflare can then cache these responses further out on its own edge network as long as Cache-Control headers allow it.
5.2 Edge Middleware for Geo or Device Personalization
Combine Next.js middleware with Cloudflare’s global proxy to personalize experiences with minimal latency:
// middleware.ts
import { NextResponse } from 'next/server';
export function middleware(request: Request) {
const url = new URL(request.url);
const country = (request as any).cf?.country || 'US'; // available when Cloudflare is in front
if (url.pathname === '/') {
url.pathname = `/home/${country.toLowerCase()}`;
return NextResponse.redirect(url);
}
return NextResponse.next();
}
With this setup, users hit Cloudflare close to them, Cloudflare forwards to Vercel’s edge runtime, and routing decisions are made with minimal round‑trip overhead.
Step 6: Prevent Common Caching Pitfalls
-
Don’t cache authenticated content at the edge unintentionally.
Ensure pages that rely on cookies, sessions, or auth tokens either:- Set
Cache-Control: private, no-store(or similar), or - Are explicitly excluded from Cloudflare cache via rules.
- Set
-
Be careful with “Cache Everything” on Cloudflare.
Use it only for clearly static paths, or you risk caching user‑specific HTML. -
Validate headers from Vercel.
Use browser devtools orcurl -I https://your-domain.com/pageto checkCache-Control,Vary, and dependency on cookies. -
Test purging and revalidation flows.
Confirm that ISR pages re‑generate as expected and that Cloudflare’s cache purges when you deploy or manually clear it.
Step 7: Observability and Debugging
7.1 Use Response Headers
Add simple headers to see where a response is coming from:
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{ key: 'x-app-platform', value: 'vercel-nextjs' },
],
},
];
},
};
Then inspect responses in your browser DevTools:
cf-cache-statusfrom Cloudflare (e.g., HIT, MISS, BYPASS, EXPIRED)- Any custom headers like
x-app-platformorx-powered-by
7.2 Cloudflare and Vercel Analytics
- In Cloudflare: check Analytics > Web Traffic and Cache tabs for cache hit ratios, geographic distribution, and error rates.
- In Vercel: review request volumes, function usage (including Edge Functions), and route‑level performance.
When to Use This Workflow
This Cloudflare + Vercel + Next.js stack is especially useful when:
- You already standardize all domains and DNS on Cloudflare.
- You want WAF, firewall rules, and bot protection on top of Vercel.
- You expect global traffic and want dual‑layer edge caching.
- You plan to experiment with edge‑based personalization and A/B testing.
Summary
By putting Cloudflare in front of Vercel and using Next.js features like ISR and Edge Runtime, you can build an architecture that is:
- Fast: Responses served from both Vercel and Cloudflare edges.
- Secure: Cloudflare WAF and SSL/TLS in front of your app.
- Scalable: Two global networks sharing the load with smart caching.
- Flexible: Middleware at the edge for routing, localization, and experiments.
If you want to go deeper into tuning this pattern for production workloads, including specific cache rules, header strategies, and example configurations, read this detailed guide: Cloudflare Vercel Workflow: Deploying NextJS with Edge Caching.
```
Comments
Post a Comment