StackResolve logoStackResolve

Freshness

Every field knows how stale it is allowed to be.

Each field has a time-to-live (TTL) based on how fast it changes. When you call a primitive, any field older than its TTL is refreshed before the answer is returned; fresh fields are served from cache. You do not get silently stale data, and you do not pay to re-fetch something that is still current.

#How it works

Every fact is stored with an expires_at set from its namespace and key TTL. A fact past that time is marked is_stale. On the next call, the engine triages the requested fields into missing, stale, and fresh, then refreshes only the missing and stale ones. A refresh writes a new fact row and supersedes the old one, keeping the confidence and the source.

#TTLs

Field groupFieldsTTL
Fast-movingrecent_news1 hour
Dailypricing, free_tier, self_serve, mcp_available, claude_compatible, codex_compatible, cursor_compatible1 day
Weeklyproducts, funding, technology, executives, api, openapi, cli, sdks, llms_txt, and the readability signals7 days
Slow-movingdescription, categories30 days

See Schemas for the per-field TTL table.

#In the response

Every research response carries a freshness block, one entry per returned field:

JSON
"freshness": {
  "description": { "observedAt": "2026-08-20T08:02:33.979Z", "stale": false },
  "recent_news": { "observedAt": "2026-08-20T08:02:34.548Z", "stale": false }
}

A profile reports the same per-fact, with observedAt and stale on each fact, plus a top-level lastChecked.

#cached vs stale

The cached flag on a research response tells you whether the whole answer came from stored facts (true) or at least one field was refreshed on this call (false). The per-field stale flag tells you the freshness state of that field. See Caching for how repeat calls stay fast and cheap.