Dynamic Sitemap: Generate and Maintain One Automatically
Static vs Dynamic Sitemaps
A static sitemap is a manually maintained XML file that you upload to your server and update whenever your site changes. A dynamic sitemap is generated on-the-fly (or on a scheduled basis) by querying your site's database or CMS to produce an always-current URL list. Static sitemaps are workable for small sites that change infrequently — a 50-page brochure site can be managed manually. For any site that publishes content regularly, powers an e-commerce catalog, or has user-generated content, a dynamic sitemap is the only practical solution; a static file becomes stale within hours of a new post or product being added.
Why Dynamic Sitemaps Matter for Large Sites
Google's John Mueller has confirmed that sitemap freshness affects how quickly new pages get crawled and considered for indexing. When you publish a new article and your dynamic sitemap updates immediately, Googlebot can discover that page in its next sitemap fetch — typically within hours if you have submitted the sitemap to Search Console. With a stale static sitemap, that new page may not be discovered until Googlebot finds a link to it from another page, which can take days or weeks. For news sites, product-heavy e-commerce stores, and SaaS platforms with frequently changing feature pages, this crawl latency has a direct impact on how quickly new content can begin ranking.
Dynamic Sitemap in Next.js
Next.js 13.3+ has built-in sitemap generation via a sitemap.ts or sitemap.js file placed in the app directory. This file exports a default function that returns an array of sitemap entries — each with a URL, lastModified date, and optional changeFrequency and priority values. You can query your database, CMS API, or any data source inside this function to produce a fully dynamic URL list at build time (for static export) or at request time (for server-rendered sites). For very large sites, Next.js also supports generateSitemaps() to produce multiple sitemap files automatically, respecting the 50,000 URL per sitemap limit and generating a sitemap index file automatically.
Dynamic Sitemap in WordPress
WordPress generates a dynamic XML sitemap out of the box since version 5.5, accessible at /wp-sitemap.xml. The default implementation is basic — it includes posts, pages, categories, and authors. The Yoast SEO and Rank Math plugins replace the default sitemap with more configurable versions that respect noindex settings, allow you to exclude post types or taxonomies, set priority and changefreq values, and automatically update lastmod on content changes. Both plugins hook into WordPress post save and update events so the sitemap reflects the current state of your content immediately after publishing, without any manual steps.
Dynamic Sitemap in Other Frameworks
In Ruby on Rails, the sitemap_generator gem connects to your ActiveRecord models and generates sitemaps on a cron schedule, uploading directly to S3 or another storage provider. Django projects commonly use django-sitemaps, a built-in framework module where you define Sitemap classes that query your ORM models and are served as XML views via URL routing. Laravel uses the spatie/laravel-sitemap package, which can crawl your site or query Eloquent models, with support for scheduling via Laravel's task scheduler. For headless architectures — sites built on React, Vue, or Svelte with a separate API — sitemaps are best generated as a serverless function or build step that queries the CMS or backend API directly.
Common Dynamic Sitemap Mistakes
The most common error is including non-canonical URLs — pages with canonical tags pointing elsewhere, noindex directives, or redirect chains should never appear in the sitemap; only include final-destination, indexable URLs. Generating inaccurate lastmod dates — such as using the current server time on every request rather than the actual content modification date — teaches Google to ignore the lastmod field entirely on your site. Failing to split large sitemaps properly causes XML parsing errors if you exceed 50,000 URLs or 50MB uncompressed in a single file; use a sitemap index to reference multiple sitemap files. Not referencing your sitemap in robots.txt means Googlebot may not discover it during initial crawls of a new domain.
Caching Your Dynamic Sitemap
Generating a sitemap dynamically on every request is expensive for large sites. A sitemap covering 10,000 product pages requires hitting your database or API 10,000 times per generation — or one large query. For production, cache the generated sitemap for 1–12 hours depending on how frequently your content changes. In Next.js, use the revalidate option in your sitemap route to set ISR revalidation intervals; a news site might use revalidate: 3600 (1 hour) while a slow-changing SaaS product page sitemap might use revalidate: 86400 (24 hours). In WordPress, both Yoast and Rank Math cache their sitemap output and regenerate only when content changes — do not disable this cache on high-traffic sites as it causes significant database load.
Dynamic Sitemaps and Headless CMS Architecture
Headless CMS setups (Contentful, Sanity, Strapi, Prismic) decouple content from the frontend, which means your sitemap must query the CMS API to know which pages exist. This is the correct approach: in your sitemap generation function, fetch all published content from the CMS API, map each item to its frontend URL, and include the CMS-reported last-modified date as lastmod. When content is published or updated in the CMS, trigger a revalidation of the sitemap via ISR on-demand revalidation or a webhook to your revalidate endpoint. The critical failure mode to avoid is a sitemap that only reflects the build-time state of content — if your headless CMS generates new pages dynamically between builds and your sitemap is only updated at build time, new content may not appear in the sitemap for hours or days.