SEO

Sitemap index or a single sitemap: when to switch

A single sitemap holds up to 50,000 URLs and 50 MB. Past that mark you need an index listing several files, with honest lastmod values and no empty file.

Key points

  • One file holds 50,000 URLs and 50 MB: past that you need a two-level index.
  • Publish lastmod only when it is true, otherwise Google ignores it.
  • An index makes changes readable, it does not grow the crawl budget.

A single sitemap is enough while the site stays under 50,000 URLs and 50 MB uncompressed; past that mark you need a sitemap index, a file that lists the other sitemaps and holds no page URLs itself. The limit belongs to the protocol, not to the server.

The two protocol limits

The protocol caps a file at 50,000 URLs and 50 MB uncompressed. An index accepts up to 50,000 sitemaps, and an index cannot list another index: the hierarchy is two levels deep, not three. gzip cuts the weight, not the URL count.

The shape is <sitemapindex> with one <sitemap><loc> element per child. lastmod is optional at every level, and Google ignores it when it is always today: a value that never changes is worse than no value.

When a single file is the right call

  • Under 5,000 URLs an index adds a request and solves nothing.
  • When every page changes together, a single lastmod is honest and readable.
  • A single file can be checked by hand in a minute, and mistakes show up at once.

When an index earns its place

  • Past 50,000 URLs, or when one file exceeds 50 MB uncompressed.
  • When sections change at different rates: a daily blog, a monthly catalogue.
  • When one section has to be left out without rewriting the whole file.

Read an index before publishing it

cat > check-sitemap.mjs ([^/g)].map((m) => m[1]);
console.log(children.length + " child sitemaps");
for (const url of children) {
  const xml = await (await fetch(url)).text();
  const urls = (xml.match(//g) || []).length;
  if (!urls) console.log("EMPTY   " + url);
  else console.log(String(urls).padStart(6) + "  " + url);
}
EOF
node check-sitemap.mjs

The script fetches the index, lists the children and counts <loc> occurrences in each one. A child with zero URLs is a defect to fix: Google reads an empty file and trusts the rest of the index less. A child with 49,000 URLs is a time bomb, because the next addition breaks the limit.

How the EneUI catalogue does it

The index opens with /sitemap-core.xml, which holds hubs, guides and libraries, then lists the component files. The 1,556 blocks and the 12,808 icons stay in the core; individual records such as sidebar from 21st live in the component files, the ones a single file could never hold. Checked on 1 November 2026.

The limitation

An index does not grow the crawl budget. If the site publishes 111,985 URLs and changes a thousand a day, Google reads a fraction: splitting into files makes the changes readable, it does not persuade a crawler to read everything. The only real lever is to stop publishing pages nobody searches for.

Where to continue

The sequence for getting into the index is in getting a site indexed by Google; how language versions are declared is in hreflang: the common mistakes. If the site base is still undecided, the comparison is in WordPress, Wix or React components.

Frequently asked questions

How many URLs fit in one sitemap?

50,000 per file, with a maximum of 50 MB uncompressed. Past that limit you split into several files and publish an index.

Can a sitemap index list another index?

No. The hierarchy is two levels deep: an index lists URL sitemaps, not more indexes.

Does the sitemap have to be declared in robots.txt?

It is not mandatory, but it helps: one Sitemap line with the absolute index URL stops Google from guessing the path.

Does every URL need a lastmod?

Only when it is true. A lastmod always set to today gets ignored, and a wrong lastmod is worse than none.

Can a sitemap be gzipped?

Yes, the protocol allows .gz files. The 50 MB limit applies to the uncompressed content.