Next.js On-Demand Revalidation lets you invalidate specific cached pages without rebuilding your entire Next.js application.

Imagine you have a blog post that’s been updated. You don’t want to wait for a full site rebuild to push that change live. On-demand revalidation is your tool for that.

Here’s a simple Next.js app demonstrating this. We’ll have a basic page that fetches data, and a separate "secret" page that can trigger a revalidation.

// pages/posts/[slug].js
import React from 'react';

export async function getStaticPaths() {
  const posts = [{ slug: 'my-first-post' }, { slug: 'another-post' }];
  const paths = posts.map((post) => ({
    params: { slug: post.slug },
  }));
  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  // In a real app, this would fetch from a CMS or database
  const postData = {
    title: `My Post: ${params.slug}`,
    content: `This is the content for ${params.slug}. Last updated: ${new Date().toLocaleTimeString()}`,
  };
  return {
    props: { post: postData },
    revalidate: 60, // Revalidate every 60 seconds
  };
}

function Post({ post }) {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
}

export default Post;

This Post component is statically generated. getStaticProps fetches data and sets a revalidate time of 60 seconds. This means Next.js will attempt to re-generate this page in the background every 60 seconds if new requests come in.

Now, let’s add the mechanism to trigger revalidation. We’ll create an API route that Next.js can call.

// pages/api/revalidate.js
export default async function handler(req, res) {
  // Check for a secret token to prevent unauthorized revalidation
  if (req.query.secret !== process.env.REVALIDATE_SECRET) {
    return res.status(401).json({ message: 'Invalid secret' });
  }

  try {
    // This should match the path of the page you want to revalidate
    // In a real app, you'd likely get this from the request body or query params
    await res.revalidate('/posts/my-first-post');
    return res.json({ revalidated: true });
  } catch (err) {
    // If there was an error, you might want to log it
    // and return an error message
    return res.status(500).send('Error revalidating');
  }
}

To make this work, you need to set an environment variable REVALIDATE_SECRET in your .env.local file:

REVALIDATE_SECRET=my-super-secret-key

When a request hits /api/revalidate?secret=my-super-secret-key, Next.js will re-generate the /posts/my-first-post page. If you visit /posts/my-first-post again, you’ll see the updated content.

The core idea is that res.revalidate('/path') tells the Next.js server to immediately queue up a regeneration of that specific path. It doesn’t rebuild the entire site. It’s a surgical strike on the cache.

You can revalidate multiple paths by calling res.revalidate multiple times within the same API route handler. You can also revalidate dynamic routes by passing parameters: await res.revalidate('/posts/['slug']', { params: { slug: 'my-first-post' } });.

The revalidate option in getStaticProps or getStaticPaths (revalidate: 60) is for stale-while-revalidate. It means that if a page is older than 60 seconds and a request comes in, Next.js will serve the old page immediately but also trigger a regeneration in the background. On-demand revalidation bypasses this timer; it forces a regeneration now, regardless of how old the page is.

A common mistake is forgetting to add the secret check in your revalidation API route. Without it, anyone could trigger a revalidation, which is a security risk. Also, ensure the path you pass to res.revalidate exactly matches the page you want to update, including any dynamic segments.

The next hurdle you’ll face is managing revalidation for complex, deeply nested data structures or when the data source itself is behind a slow API.

Want structured learning?

Take the full Nextjs course →