Netlify NextJS preview returns stale data for specific document type

4 replies
Last updated: Jun 30, 2021
I got a curious issue with deploying NextJS on Netlify where a preview (/api/preview?…etc.; I’m not using PreviewSubscription at the moment) for a specific document type get SSR-ed’ perfectly fine locally with
next build && next start
, but when deployed, always returns stale data.
It doesn’t happen with other document types. Logging of the deployed functions show the same configurations (correct token, correct document id, useCdn: false). I’m super puzzled — any one had this issue before?
AI Update

This is a tricky issue! The fact that it's only affecting one specific document type is the critical clue here — this suggests it's not a general CDN or caching problem, but something specific to how that particular document type's data is being fetched or configured.

Here are the most likely Sanity-specific culprits and troubleshooting steps:

1. Check Your Perspective Configuration

Since you're fetching draft content for preview, ensure you're using the correct perspective when querying. The previewDrafts perspective is what returns draft content:

const client = createClient({
  // ... other config
  useCdn: false,
  perspective: 'previewDrafts', // Critical for preview mode
  token: process.env.SANITY_API_READ_TOKEN // Required for drafts
})

Important: If you recently updated to API version 2025-02-19, the default perspective changed from raw to published. If your working document types explicitly set perspective: 'previewDrafts' but this problematic one doesn't (or uses a different client instance), it might be falling back to the default published perspective, which would explain the stale data. This is especially likely if you have type-specific data fetching logic.

2. Verify Draft Document Existence

For this specific document type, check whether draft versions are actually being created in your dataset. You can verify this by querying directly in Vision or your code:

*[_type == "yourProblemDocType" && _id in path("drafts.**")]

If drafts aren't being created properly for this type (perhaps due to schema configuration, custom actions, or publishing workflows), you'd be fetching the published version even in preview mode.

3. Compare GROQ Queries Between Types

Look at the GROQ queries used for the working vs. non-working document types. The problematic type might have:

  • Reference projections that don't handle drafts properly
  • Joins that inadvertently filter to published versions only
  • Custom filtering that excludes draft documents

For example, if you're doing reference expansion:

// This might cause issues - the -> only fetches published references
*[_type == "problemType"][0]{
  ...,
  "author": author->{ name }
}

If the problematic document type has more complex queries with references, those references might not be respecting the draft state.

4. Check for Type-Specific Client Configuration

Search your codebase for any code paths where you might be creating different client instances for different document types. For example:

// Bad - if this only happens for certain types
const clientForThisType = createClient({
  useCdn: true, // This would cache!
  perspective: 'published', // Wrong for previews
})

Also check if you're using sanityFetch differently for this type — it has its own caching behavior that could cause issues if configured incorrectly.

5. Investigate Next.js Route-Level Caching

In Next.js 13+ App Router, check if there are route segment configs that might be caching this specific type differently:

// In your route file - make sure this isn't set for preview routes
export const revalidate = 3600 // This would cache for an hour
export const dynamic = 'auto' // Should be 'force-dynamic' for previews

6. Test Document ID Patterns

Add detailed logging to your preview route to see what's actually being returned:

const data = await client.fetch(query, params)
console.log('Returned document ID:', data._id)
console.log('Is draft?', data._id?.startsWith('drafts.'))
console.log('Perspective used:', client.config().perspective)

Deploy this logging and check your Netlify function logs. If the _id doesn't start with drafts., you're not getting draft content, which points to a perspective/query issue rather than caching.

7. Clear and Test Fresh

  1. Create a brand new document of the problematic type and test preview — does it work for new documents but not old ones?
  2. Clear Netlify's deploy cache (Deploys → Trigger Deploy → Clear cache and deploy) to rule out build-time issues
  3. Compare schemas side-by-side between working and non-working types — look for differences in custom actions, workflows, or preview configurations

Why This Matters

The single-document-type failure pattern strongly suggests:

  • A query-level issue specific to that type's structure
  • A client configuration that's conditionally applied based on document type
  • A schema difference that affects how drafts are created or fetched

It's very unlikely to be a general Netlify CDN issue, since that would affect all document types equally. Focus your debugging on Sanity-specific configuration differences for this type.

If you share the GROQ query for the problematic type and how you're initializing the client for it, the community might be able to spot the specific issue!

Show original thread
4 replies
Is it possible you’re seeing caching of the static page vs the client refreshing the json for a page (and client side rendering it with more recent data)? I haven’t fully explored this but hard refreshes on some of our pages will result in old data but getting there by a client side router link will show up to date data. Maybe these are related? Sorry if not
Thanks Chris, that sounds like a possibility — I’ll check
just wanna circle back to share the issue that I ran into: https://github.com/netlify/netlify-plugin-nextjs/issues/440
Netlify’s on-builder functions send me cached response on preview pages

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?