File Uploaded but CDN Still Returns 404? Troubleshooting Negative Caching, Cache Keys, and Purge Paths
Create Time:2026-09-24 15:38:19
浏览量
1027

CDN edge nodes serving a cached 404 while the origin file is available

Uploading a missing file does not always make a CDN-served URL work immediately. If the first request reached the origin before the file existed, an edge node may have cached the 404 Not Found response. A purge can also miss when it targets a URL that does not match the CDN's actual cache key, or when the hostname routes to a different origin than the one you updated.

The fastest way to fix this is to stop treating every 404 as the same failure. First identify which layer generated the response, then compare the exact cache key, confirm the selected origin, and purge only the affected object. Change error-cache settings only after the request path is understood.

Start by locating the layer that generated the 404

Test the public CDN URL and the origin separately. Preserve the original Host header when the origin uses virtual hosts, because testing the origin IP without it may hit a default site and produce a misleading result.

# Public CDN URL
curl -sS -D - -o /dev/null https://cdn.example.com/assets/app.js

# Origin test while preserving the production hostname
curl -sS -D - -o /dev/null \
  --resolve cdn.example.com:443:203.0.113.10 \
  https://cdn.example.com/assets/app.js

Compare the status code, response time, Age, Via, cache-status headers, request ID, and any provider-specific edge headers. Header names vary by CDN, so do not rely on one field alone.

  • Origin is 404 and CDN is 404: the object path, deployment, origin routing, or permissions are still wrong. Purging the CDN will not repair an origin-side miss.

  • Origin is 200 and CDN is 404: a cached error response, a cache-key mismatch, or an edge-to-origin configuration difference is likely.

  • Results vary by location or resolver: different edge locations may hold different cache entries, or DNS may be sending clients to different CDN properties.

Also test both GET and HEAD if your application or monitoring system uses them. Some origins, object storage gateways, or custom rules handle the two methods differently.

Understand why a 404 can remain after the file appears

CDNs can cache error responses to protect the origin from repeated requests for missing objects. This behavior is often called negative caching. It reduces origin load during scans, broken-link bursts, and deployment gaps, but it also means a temporary 404 can outlive the condition that caused it.

The effective lifetime of the cached error may come from more than one place:

  • the CDN's default negative-cache policy;

  • a provider setting for error-response TTL;

  • origin headers such as Cache-Control or Expires;

  • a reverse proxy in front of the origin;

  • custom edge logic or a cache rule that applies to the path.

Do not assume that uploading the file invalidates an existing 404. From the cache's point of view, the cached response is still valid until its TTL expires or the matching cache entry is purged.

for i in 1 2 3; do
  date -u
  curl -sS -D - -o /dev/null https://cdn.example.com/assets/app.js
  sleep 5
done

A rising Age value on repeated 404 responses is strong evidence that an intermediary is serving a cached object. The absence of Age does not prove that no cache is involved, because products expose cache metadata differently.

Verify the exact cache key before you purge

A purge works only when it identifies the same cache entry used by the request. The cache key commonly includes the scheme, hostname, path, and selected query parameters. Depending on configuration, it may also vary by headers, cookies, device type, language, or custom edge variables.

Check these details carefully:

  1. Is the request using http or https?

  2. Is the hostname exactly the same, including aliases such as www, static, or a custom CDN domain?

  3. Does the path differ by case, trailing slash, URL encoding, or duplicated slash?

  4. Are query parameters ignored, sorted, included, or selectively excluded?

  5. Does a rule vary the cache by cookie, header, country, or device class?

  6. Does the purge API expect the public URL, the normalized URL, or a provider-specific cache tag?

These URLs may or may not map to the same cache entry:

https://cdn.example.com/assets/app.js
https://cdn.example.com/assets/App.js
https://cdn.example.com/assets/app.js?v=42
https://static.example.com/assets/app.js

Never add random query strings as the permanent fix. A cache-busting parameter can create a new cache key and make one request succeed while the original URL still serves the cached 404. That is useful as a diagnostic clue, but it does not clean up the broken entry.

Confirm that the CDN reaches the origin you actually updated

If the file exists on one server but the CDN routes to another, the CDN is correctly reporting that its selected origin cannot find the object. This happens often with multi-origin configurations, blue-green deployments, storage buckets, and path-based routing.

Verify the complete route:

  • CDN property or distribution attached to the public hostname;

  • behavior or route that matches the requested path;

  • selected origin host and port;

  • origin path prefix or rewrite rule;

  • object key after URL decoding and normalization;

  • virtual-host mapping and TLS server name;

  • storage-bucket region, endpoint type, and access policy;

  • deployment status across every origin node.

On a web server, confirm the file and the final filesystem path:

namei -l /var/www/example/assets/app.js
stat /var/www/example/assets/app.js

On object storage, distinguish between a truly missing object and an access-control response. Some storage services intentionally return 404 instead of 403 to avoid revealing whether a private object exists. Test through the same authenticated origin mechanism the CDN uses rather than assuming that a public browser request is equivalent.

Purge the correct object with the smallest safe scope

Once the origin returns 200 for the exact production request, purge the affected public URL. Prefer a single-file purge, cache tag, or narrow path over a full-zone purge. A broad purge can create a sudden origin traffic spike and remove healthy cached objects that were unrelated to the incident.

After sending the purge request:

  1. Record the purge request ID and timestamp.

  2. Wait for the provider to report completion rather than assuming the API response means every edge has finished.

  3. Request the exact URL again without changing the query string.

  4. Test from at least two networks or regions when the CDN is globally distributed.

  5. Confirm that the returned body is the intended new object, not merely a 200 response from a fallback page.

Use a content checksum when correctness matters:

curl -fsS https://cdn.example.com/assets/app.js | sha256sum
curl -fsS --resolve cdn.example.com:443:203.0.113.10 \
  https://cdn.example.com/assets/app.js | sha256sum

Matching checksums are a stronger validation than matching status codes.

Tune error caching only after the path is fixed

Reducing the negative-cache TTL can shorten recovery from temporary deployment gaps, but setting every 404 to zero is not automatically safer. Bots and broken links can then reach the origin on every request, increasing load precisely when the site is already under stress.

Use a measured policy:

  • keep a short 404 TTL for release-sensitive asset paths;

  • use a longer TTL for obviously invalid or abusive paths;

  • avoid caching authentication and authorization failures unless the behavior is explicitly designed and tested;

  • document whether origin cache headers or CDN settings take precedence;

  • test the rollback before changing production rules.

For Nginx-based reverse proxies, a configuration may explicitly cache status codes for different periods:

proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;

Treat this as an example, not a universal recommendation. The appropriate value depends on deployment frequency, origin capacity, traffic patterns, and the CDN layer in front of Nginx. Validate the configuration before reloading and retain the previous version for rollback.

Prevent stale 404s during future deployments

The cleanest fix is to remove the interval in which a new URL is referenced before its object is available.

For static sites and frontend bundles, use this deployment order:

  1. Upload content-addressed assets such as app.8f3c1a.js.

  2. Verify the assets directly at the origin.

  3. Publish the HTML or manifest that references them.

  4. Purge only mutable entry points such as index.html when needed.

  5. Keep previous versioned assets long enough for cached HTML and active sessions to finish using them.

Add a pre-release check that requests every asset in the generated manifest from the production origin route. If a CDN must serve a stable filename, upload the new object first, verify it, and then perform a targeted purge. Avoid deleting the old object before the replacement is globally available.

A practical troubleshooting order

When a newly uploaded file still returns 404 through the CDN, use this order:

  1. Reproduce the exact public URL and save the response headers.

  2. Test the origin with the production hostname preserved.

  3. Confirm the object key, permissions, route, and deployment status.

  4. Compare hostname, path, query parameters, and other cache-key inputs.

  5. Inspect negative-cache and error-TTL rules at every caching layer.

  6. Purge the exact public cache entry.

  7. Re-test from multiple edges and compare the response body or checksum.

  8. Adjust error caching only if the current policy does not fit the deployment model.

  9. Change the release sequence so references are published after assets exist.

The key distinction is simple: a purge removes a cache entry, but it cannot correct a wrong origin path; an origin upload creates an object, but it does not necessarily remove a cached error. Diagnose both sides of that boundary before changing global cache settings.

Official references