Keys and vary
Cache keys decide whether two requests can reuse the same response. Layeron builds keys deterministically so route handlers and product Workers can agree on the same Cloudflare Cache entry.
Key Shape
Section titled “Key Shape”apiCache.key(request) returns a URL-like key:
const key = apiCache.key( new Request("https://api.example.com/products?limit=20", { headers: { "accept-language": "en-US", }, }),)Layeron normalizes the key by:
- Removing URL fragments.
- Sorting query parameters.
- Adding the instance namespace.
- Adding the uppercase HTTP method.
- Adding configured vary header values.
Namespace Partitioning
Section titled “Namespace Partitioning”Cache keys include the platform namespace:
const marketingCache = cache({ name: "pages", namespace: "marketing",})
const appCache = cache({ name: "pages", namespace: "app",})Both instances use the same name while producing separate keys and stats. See
Namespaces for platform namespace behavior.
Method
Section titled “Method”The HTTP method is part of the key. A GET /items response and a
HEAD /items response are separate entries.
For API response caching, use GET and HEAD routes. Write routes usually
perform purge after changing data.
Query Parameters
Section titled “Query Parameters”Query parameters are sorted before the key is created:
/api/products?sort=price&limit=20/api/products?limit=20&sort=priceThese requests map to the same key after normalization.
High-cardinality query parameters produce many entries. Use small TTLs for search, autocomplete, and highly personalized filters.
Vary Headers
Section titled “Vary Headers”vary adds selected request header values to the key:
const apiCache = cache({ name: "localized-api", vary: ["accept-language"],})Use vary for dimensions that change the actual response body:
| Header | Use Case |
|---|---|
accept-language | Localized content. |
accept | JSON, HTML, or alternate media formats. |
x-tenant-id | Tenant-specific public data when your app controls the header. |
Keep vary lists short. A header with many unique values creates many cache entries.
Per-Call Vary
Section titled “Per-Call Vary”You can override vary for one operation:
await apiCache.put(request, response.clone(), { vary: ["accept-language", "accept"], tags: ["products"],})
const cached = await apiCache.match(request, { vary: ["accept-language", "accept"],})The same vary list must be used for match, put, and delete when it differs
from the cache instance default.
Tags and Keys
Section titled “Tags and Keys”Tags are stored with entries for invalidation. They stay outside the cache key.
await apiCache.put(request, response.clone(), { tags: ["products", "product:123"],})The same request can later be matched with only the request:
const cached = await apiCache.match(request)This keeps reads simple while preserving tag-based purge behavior.