What we cache
| Endpoint shape | Default TTL |
|---|---|
List endpoints (/v1/cards, /v1/sets) | 300 seconds |
Resource endpoints (/v1/cards/{id}) | 3600 seconds |
Anything with ?updated_since= | 60 seconds |
updated_since shortened TTL exists because that filter exists to catch recent changes; caching it for an hour would defeat the purpose.
The cache key is composed of:
- The path
- The query parameters (sorted, so
?a=1&b=2and?b=2&a=1hit the same entry) - The API tier of the requesting key (Free and Partner use separate cache namespaces)
- The
Acceptheader
Accept: application/json to no Accept header, you’ll see a fresh fetch on the first request after the switch.
Reading cache state
Every response carriesmeta.cached:
true means we served from edge cache; false means the Worker hit the origin database. During a steady-state production workload, you should see this run 80–95% true. Deviation from that is signal.
What busts the cache
Two things invalidate cached entries:- TTL expiry. Whichever of the values above applies.
- Set publish. When a new set goes live in the Elestrals admin system, an internal webhook purges everything tagged with
cards,sets,printings, andseries. You’ll see fresh data within seconds of a release.
?updated_since=<ISO timestamp> instead.
Caching on your end
Stacking your own cache on top of ours is encouraged. A few rules of thumb:- By resource ID. Cache
/v1/cards/{id}responses keyed by the card ID. These rarely change after a card has been live for 30 days; long TTLs are safe. - By query. Cache list responses keyed by the full query string. Use a short TTL (1–5 minutes) and rely on the same cache key whether the response was a hit or a miss on our edge.
- Honor the response, not the request. Cache by what you got back, not by what you asked for. The
meta.request_idis unique per request and shouldn’t make it into your cache key.
When not to cache
A handful of patterns aren’t worth caching:- Polled
?updated_since=queries. You’re already polling for change; caching the response defeats the loop. - Health checks.
/v1/healthis uncached on our end and shouldn’t be cached on yours either. - One-shot scripts. A migration job that runs once and dies has no cache to populate.