Caching

Every response says how long it may be kept, in one of three classes.

ClassHeaders
Data, with ?lang=public, max-age=300, s-maxage=86400 and an ETag
Data, language from the headerprivate, max-age=300 and an ETag
Geo, validateprivate, no-store

The data routes are /v1/countries, /v1/countries/:country and its /states, /v1/locales/:lang and /v1/version. The per-visitor routes are /v1/geo, with or without ?include=, and POST /v1/validate, whose body is what a shopper typed.

Language and shared caches

A body whose language came from Accept-Language varies by a header its URL does not name, so a shared cache keyed on the URL would hand one visitor's language to the next. Those responses are private. A client that wants a shareable URL sends ?lang=, which the SDK always does.

Geo is never stored

A cached geo response would serve one visitor's country, city, postcode and IP address to the next, so /v1/geo is no-store and carries no ETag. A test asserts it. Because it is never cached, a form that detects its country with ?include=rules always starts with the current rules; /v1/geo?include=rules&country=XX does the same for a fixed country.

Revalidation

An ETag combines the data version, the deployed version, the language of the body and the query string, so a change to the data, to the code or to the language asked for is a new tag. If-None-Match is compared as RFC 9110 says: a list of tags, weak or strong, or *. A match gets a 304 with no body.

Browsers keep a response for 5 minutes, then revalidate with the ETag, so a deploy reaches a browser within 5 minutes and a cache outside Cloudflare that honours s-maxage within a day.

The edge

The Worker answers every request. Cloudflare runs a Worker before its cache, and this one does not put responses into it, so s-maxage is for caches outside Cloudflare. Each request costs well under a millisecond of work. The flags are the exception: they are static files, served without running the Worker and cached for a week.