Discussion on cache problem and webhook usage for updating blog posts on Nextjs hosted on Vercel with Sanity.io.

12 replies
Last updated: Jan 7, 2021
Hello. I believe I have some sort of cache problem. I have a blog on Sanity and when I create or edit blog posts I can see the update instantly when I publish it on local but it takes close to 5-10min to appear on production. Ultimately it does appear but I'm wondering why this is happening.My blog is on Nextjs, hosted on Vercel.
AI Update

This is a classic Next.js caching issue, not a Sanity problem! The 5-10 minute delay you're seeing is almost certainly due to Next.js's built-in caching layer that isn't being revalidated when you publish content in Sanity.

When you're working locally, you're likely in development mode where Next.js doesn't cache as aggressively, which is why you see updates instantly. But in production on Vercel, Next.js caches pages to improve performance, and those cached pages won't automatically update when you publish content in Sanity.

The Solution: Set up on-demand revalidation

You need to tell Next.js to refresh its cache when content changes in Sanity. Here are your options:

Option 1: Sanity Functions (Modern Approach)

The modern, recommended approach is using Sanity Functions to automatically trigger Next.js revalidation when content changes. Functions are serverless compute that run within Sanity, so you don't need external hosting. They can listen for document changes and call your Next.js revalidation endpoint automatically.

Option 2: Webhooks + Next.js Route Handler (Traditional Approach)

If you prefer the traditional webhook approach, here's how to set it up:

Step 1: Create a Next.js API route for revalidation

For App Router (/app/api/revalidate/route.ts):

import { revalidatePath, revalidateTag } from 'next/cache'
import { NextRequest, NextResponse } from 'next/server'

export async function POST(request: NextRequest) {
  const secret = request.nextUrl.searchParams.get('secret')
  
  if (secret !== process.env.REVALIDATION_SECRET) {
    return NextResponse.json({ message: 'Invalid secret' }, { status: 401 })
  }

  // Revalidate specific paths
  revalidatePath('/blog')
  revalidatePath('/blog/[slug]')
  
  // Or use tags if you've set them up
  // revalidateTag('blog-posts')

  return NextResponse.json({ revalidated: true, now: Date.now() })
}

Step 2: Set up a webhook in Sanity

  1. Go to sanity.io/manage
  2. Select your project
  3. Go to "API" β†’ "Webhooks"
  4. Create a new webhook pointing to: https://yourdomain.com/api/revalidate?secret=YOUR_SECRET
  5. Set it to trigger on "Create", "Update", and "Delete" for your blog post document type

Which revalidation method should you use?

  • revalidatePath() - Use when you know specific URLs that need updating (like /blog or /blog/my-post-slug). Good for simple blogs.

  • revalidateTag() - More flexible if you tag your data fetching. Great for interconnected content where blog posts reference authors, categories, etc. You'd tag your fetch requests like fetch(..., { next: { tags: ['blog-posts'] } }) and then revalidate all related content at once.

Additional tips

  • Add a secret token to your revalidation endpoint (as shown above) to prevent unauthorized revalidation
  • Store the secret in your Vercel environment variables
  • You can also set up time-based revalidation as a fallback by adding revalidate: 600 (10 minutes) to your data fetching, but on-demand revalidation is better for immediate updates

The Sanity documentation has a full course on controlling cached content in Next.js that walks through all these approaches in detail. Once you set this up, your production site should update within seconds of publishing, just like in development!

Oh. Do I have to create some sort of webhook to force a ploy every time there's a published update?
Depends how you're fetching your data from Sanity. If you're using getStaticProps without revalidate, you'll need to deploy on Vercel after making a change. If you're using revalidate or fetching via getServerSideProps, getPromise, etc., you shouldn't need to redeploy.
As for the 5-10 mins, that's probably due to
useCdn: true
when you configure your sanityClient.
Thanks for your reply
user A
. It's now working with a webhook from Vercel.
Nice! πŸŽ‰
It actually take 2 deploys to actually update the content with a webhook. Do you think this is because of the CDN?
Ah yes apparently. I'll try without to see how it goes.
You would want to set
useCdn: false
.
In case
useCdn: false
doesn't work: there might be a slight sync delay between when the webhook is fired and when the data is available from the API. You could consider calling a serverless function instead, which then calls the Vercel deploy hook after a short timeout to prevent having to do 2 deploys πŸ™‚
You might not need the webhook though, as Geoff suggested above.
Ah very true. I changed the request to be on every render server side and it works great. For some reason most example out there on Nextjs uses getStaticProps so I assumed it was best practice but it's much easier to do it per render to avoid having to do too much work on webhooks.
(Heads up: keep an eye on your API request usage statistics in case things need to be more frugal πŸ™‚)
Will do. Yes I can see it being a problem with higher traffic. We are fairly small for now so all good.
Will do. Yes I can see it being a problem with higher traffic. We are fairly small for now so all good.

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?