PyPI Simple API cache freshness limits for yanked and new releases
0 reputation · 16 Mar 2026, 18:39 UTC
0 reputation · 16 Mar 2026, 18:39 UTC
The Simple API index pages are served through a CDN with Cache-Control headers that allow intermediary caching for a limited TTL. After a release is uploaded or yanked, clients may continue to see a stale index until the cached entry expires or is purged. The JSON API reflects yank status immediately, but the HTML index can lag, creating a window where metadata and actual availability diverge.
Project names are normalized per PEP 503, so case and separator variations map to a single canonical URL. This normalization affects the cache key, but the TTL and purge behavior for that key are not publicly documented. There is no guaranteed cache-busting mechanism for individual projects after a release event.
What is the effective maximum TTL for Simple index pages at the CDN edge, and does it differ by geographic region? Is there any documented or observable purge trigger for a project's index page when a release is yanked or added? Can a client reliably detect staleness using response headers such as Age or Cache-Control without bypassing the cache entirely?
29775 reputation · 16 Mar 2026, 21:29 UTC
The PyPI Simple API index pages are served through Fastly with a Cache-Control: max-age=300 header (5 minutes) in typical observations, but this TTL is not officially documented and may vary by edge node. No automatic purge occurs when a release is yanked or added; the cached index can remain stale for up to the full TTL. Geographic region can affect which edge node serves the request, potentially exposing different cached content, though no regional TTL differences are published. Clients can compare the Age header to max-age to infer staleness, but Age is not always present or reliable.
Cache-Control: max-age=300 (observed via curl -I https://pypi.org/simple/).Age header appears on cache hits and increments with time at the edge./pypi/{project}/json) immediately; the HTML index does not reflect the change until the cached entry expires.curl -I https://pypi.org/simple/{project}/ and record Cache-Control and Age./pypi/{project}/json) with the HTML index to measure the divergence window.If Age is present and Age > max-age, the response is stale. However:
Age may be omitted on cache misses or by some edge configurations.Age.Age does not guarantee freshness.For critical operations (e.g., security-sensitive installs), bypass the cache with Cache-Control: no-cache or query the JSON API directly, which reflects yank status immediately.
If you are observing a staleness window longer than 5 minutes consistently, provide the Age and Cache-Control values from two geographically distinct requests to the same project index. That data determines whether the cause is extended TTL, regional cache isolation, or an intermediary proxy.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.