Publish in Payload, invalidate precisely in Next.js
How we use cache tags to connect Payload CMS publish events to precise Next.js page updates, no full rebuilds, no stale content.
The Blog
Most CMS sitemaps are generated once and forgotten. Ours split by collection, cache aggressively, and invalidate the moment content is published, unpublished, or deleted.
The problem
A sitemap tells search engines which pages exist and when they last changed. When it's accurate, it helps Google prioritise crawling, new and recently updated pages get found faster.
When it's inaccurate, listing pages that no longer exist, showing stale lastmod dates, or including unpublished drafts, it does the opposite. Google learns the sitemap isn't trustworthy and starts ignoring it, relying on its own crawl discovery instead. Your sitemap becomes noise rather than signal.
Most CMS-generated sitemaps have this problem. They're built at deploy time and not updated until the next build. Between builds, every publish, unpublish, and delete makes the sitemap a little less accurate.
The approach
We split sitemaps by content type, cache them for performance, and invalidate them precisely when content changes. Here's the pattern.
Instead of one monolithic sitemap, we generate separate sitemaps for each content type, pages, posts, and work. Each sitemap route queries only its own collection, requesting only the fields it needs: slug, breadcrumbs (for nested pages), and updatedAt for the lastmod timestamp. Smaller, faster, and each can invalidate independently.
Each sitemap route is wrapped in unstable_cache with its own tag, pages-sitemap, posts-sitemap, work-sitemap. The sitemap is generated once and served from cache on every subsequent request. Fast responses, minimal database queries, no redundant work.
The same collection hooks that handle page cache invalidation also revalidate the relevant sitemap tag. Publish a blog post, posts-sitemap tag is busted, next request regenerates the sitemap with the new post and its current lastmod. Unpublish or delete, same tag, same result, the removed page disappears from the sitemap immediately.
Sitemap queries filter for published documents only with overrideAccess: false. Draft content never appears in sitemaps, regardless of cache state. This matters more than it sounds, a leaked draft URL in a sitemap can lead to Google indexing content that isn't ready.
Why this matters
A sitemap that accurately reflects the current state of your site earns Google's trust. When lastmod dates match actual content changes, Google is more likely to recrawl those URLs promptly. When the sitemap only includes live, published pages, there's no noise from old URLs or draft content.
For sites that publish frequently, weekly blog posts, regular case study updates, seasonal page changes, sitemap accuracy compounds. Each accurate signal reinforces the next. Each inaccurate one erodes it.
The overhead of getting this right is minimal. The sitemap routes are simple, a cached database query filtered by collection and status. The invalidation hooks are already in place for page caching. Adding sitemap tags to those hooks is a single line per collection.
Small infrastructure work. Ongoing crawl benefit.