advanced 2 min answer

After a price change you issue a CDN purge and every point of presence returns 200. Twenty minutes later customers in one region still see the old price, and a hard refresh fixes it for some of them. Where do you look and in what order?

cdnpurgecache-variantsvaryakamai
Show the full answer Hide the answer

The misleading clue

The 200 means the purge request was accepted, not that the object a customer is being served was invalidated. Well-run CDNs propagate a purge in seconds, so twenty minutes later this is not propagation — it is either a different object or a different cache.

The first three things I would look at

  1. The response headers from an affected client: Age, the provider's cache-status header, Cache-Control and Vary. Age localises the failure immediately. A large Age with a cache hit means an edge object survived; Age: 0 with a stale price means the origin served it, and the problem is not the CDN at all.
  2. The Vary dimensions. A purge by URL invalidates one cache key. If responses vary by Accept-Encoding, Accept-Language, a device class or a query parameter, there are many objects for that URL and you purged one of them. This is the single most common cause of "purged and still stale".
  3. The browser and the app. If the hard refresh fixes it for some users, a client-side cache is holding a copy, and no purge reaches a browser. A long max-age in Cache-Control is an irrevocable promise for its duration.

Then, if all three are clean: the mid-tier or shield cache between edge and origin, the origin's own cache, a corporate or ISP proxy, and any stale-while-revalidate or stale-if-error window that permits serving the old object while a refresh happens in the background.

The fix, in order of durability

  • Immutable URLs for anything you can rename. A price fragment or asset addressed by content hash is never stale and never needs purging. This is the only one of these that cannot go wrong.
  • Surrogate keys, also called cache tags. Tag every object that contains a product's price with that product's id, and purge the tag. One call invalidates every variant, in every region, whatever the URL looks like.
  • Split the TTLs. A short max-age for the browser and a long s-maxage for the CDN gives you edge caching you can revoke and client caching you cannot be trapped by.
  • A synthetic probe that measures purge-to-visible latency from several regions, so the property you rely on is monitored rather than assumed. A CDN in the mould of Akamai or Fastly will propagate in well under a second; what you are really monitoring is your own key structure.

When this is not worth solving

For content that changes a few times a day, a 60-second TTL removes the entire problem and costs a negligible amount of origin traffic. Purge machinery earns its keep when objects are expensive to generate, cached for hours, and must change immediately — prices, stock levels, published articles. If you find yourself building tag propagation for a page with a two-minute TTL, the TTL was the answer.