Balancing Freshness and Scale with Vercel On-Demand Revalidation
Learn how to use Vercel's Incremental Static Regeneration (ISR) and on-demand revalidation to keep content fresh without sacrificing edge performance.
01 Jul 2025, 07:00 UTC

Content-heavy sites often face a performance paradox: you want the speed of static pages cached at the edge, but you need the flexibility of a dynamic site where an editor's "Publish" button reflects changes immediately. Waiting for a full site rebuild is impractical for sites with thousands of pages, and relying solely on time-based caching can leave users staring at outdated information.
The engineering solution is Incremental Static Regeneration (ISR) paired with on-demand revalidation. This approach allows you to serve static HTML from Vercel's edge network while providing a mechanism to purge and regenerate specific pages the moment content changes.
How ISR Operates at the Edge
ISR allows pages to be generated at build time but updated in the background without a full redeploy. When a page is configured with a revalidation interval, Vercel serves the cached version to users. Once the interval expires, the next request triggers a background regeneration of that specific page. Until the new version is ready, Vercel continues to serve the stale version—a pattern known as stale-while-revalidate.
While time-based ISR is useful for data that changes predictably (like a weather widget), it is insufficient for editorial workflows. On-demand revalidation solves this by allowing an external trigger—usually a CMS webhook—to tell Vercel exactly which path needs to be refreshed, regardless of the time interval.
Implementing the On-Demand Revalidation Pattern
To implement this, you create a protected API route that acts as a gateway between your CMS and Vercel's cache. When an editor saves a post, the CMS sends a POST request to this route, which then invokes the revalidation logic for the specific URL.
Example: Next.js Pages Router Implementation
First, define the page with a fallback strategy. In this example, fallback: 'blocking' ensures that if a page hasn't been generated yet, the server will render it on the first request rather than showing a loading state.
// pages/posts/[slug].js
export async function getStaticProps({ params }) {
const data = await fetchPost(params.slug);
return {
props: { data },
// Time-based fallback: regenerate at most every 60 seconds
revalidate: 60
};
}
export async function getStaticPaths() {
return {
paths: [], // Generate pages on-demand to keep build times low
fallback: 'blocking'
};
}Next, create the revalidation API route. This route must be secured to prevent unauthorized users from purging your cache and spiking your function usage.
// pages/api/revalidate.js
export default async function handler(req, res) {
// Only allow POST requests
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method Not Allowed' });
}
// Verify the secret token provided by the CMS webhook
const secret = req.headers['x-revalidate-secret'];
if (secret !== process.env.REVALIDATE_SECRET) {
return res.status(401).json({ message: 'Invalid token' });
}
const { path } = req.body;
try {
// Trigger the revalidation for the specific path
await res.revalidate(path);
return res.json({ revalidated: true, path });
} catch (err) {
return res.status(500).json({ message: 'Error revalidating' });
}
}Execution Details: Run this code on Vercel. You must define REVALIDATE_SECRET in the Vercel Project Environment Variables. The CMS webhook should be configured to send a POST request with the secret in the header and the page path (e.g., /posts/my-first-blog) in the JSON body.
Verification and Risks
To verify the setup, deploy the site and check the x-vercel-cache header in the browser's network tab. A HIT indicates the page is served from the edge. After triggering the revalidate API route, the next request for that path should result in a MISS or STALE while the new version is generated, followed by a HIT once the update is propagated.
There are critical limitations to consider:
- Webhook Reliability: If the CMS fails to deliver the webhook or the API route returns an error, the page remains stale. There is no built-in "retry" mechanism in ISR; you must handle this at the CMS or middleware level.
- Path Management: Revalidation is path-specific. If a change in one page affects the navigation menu across the entire site, you must revalidate every single page or use a shorter time-based revalidation for shared components.
- Function Costs: While ISR is efficient, triggering thousands of revalidations simultaneously can increase your Serverless Function invocation count.
To roll back a change that caused a broken page to be cached, you can either fix the content in the CMS and trigger a new revalidation or trigger a full deployment to purge the entire edge cache.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.