Skip to main content
Answers are computed asynchronously, seconds behind writes while the engine is healthy. Instead of hiding that, every answer says how current it is.

Freshness states

Freshness is worked out when the answer is read, from the answer, the document and the judgment’s policy. The first row that applies wins: An on_read answer that isn’t current is never left stale by a get or query: reading it starts its evaluation, so it reads pending, with the last good numbers and the revision they were computed for, until the new answer lands. Only while judging is paused does it read stale (judging_paused), since nothing would judge it. A stale answer always says why in stale_reason; no other answer has one. The contract also lists block_over_cap, which is reserved: nothing reports it, and a block past its cap reads limit_reached. For a judgment with relations, “the document changed since the answer” means that something the answer’s position does not cover touched it:
  • A write after the answer’s watermark to the document itself, or to a document that pointed at it before or after the write. So a new ticket makes its account pending, and the account is fresh again once an answer lands with a watermark at or above the ticket’s write.
  • Another judgment’s answer that one of its relations shows, when the answer moved in a way the relation shows, such as crossing a band. See roll-ups.
  • A write to a candidate in its block, for a blocking relation. The block’s documents are pending until the block is read again; if nothing they read changed, they are fresh again with no engine call.
  • A change to the document it points at, inside the re-judge scope. See fan-out.

Deferral and catch-up

A change whose fan-out would pass the judgment’s rolling limit, or whose block is past block_cap, is deferred rather than run or dropped. Its answers read stale (limit_reached), the change in a get’s referenced_changes has deferred: true, and the events feed records one judgment.limit_reached naming the limit. It runs on its own, with no request from you, when older re-judgments leave the 30-day window, or at once when a PATCH raises rolling_limit or block_cap. Until then, answers: "fresh_only" leaves its answers out. A document written a moment ago under an on_change judgment reads pending, not unavailable: its first answer is on its way. unavailable means nothing is coming: the policy is on_read (until a get or query asks for the answer), manual or periodic, judging is paused (an on_change judgment judges the document once the pause ends), or the document was already there when the judgment was created and waits for a backfill. stale and failed answers still carry the last good numbers and the revision they were computed for. A failed answer for a document that was never judged successfully has no numbers. The next write to a document starts a new attempt, so failed gives way to pending or stale. A document that failed for a reason of its own, or is still failing 24 hours after it last changed, keeps its failed answer until it is written again or a backfill re-judges it, rather than being retried; see evaluations. To read only fresh answers, pass answers: "fresh_only" to a query. To wait for an answer after a write, pass wait_for to the write; an answer not ready when it times out comes back pending in the write’s response, whatever this table would say on a get. To wait for the on_read answers a get starts, pass wait_ms (at most 10,000) to the get.

Freshness and subscriptions

A subscription evaluates a document only when the answers its filter reads are settled for the document’s current revision, so its events never follow an answer that is about to change. This is the settle rule, and it reads the states above:
  • pending, and stale with judging_paused, wait. A new answer is on its way, or will be once judging resumes, and the document is evaluated when it lands. So a write never makes a document leave on a pending answer and come back a few seconds later.
  • failed holds. The document keeps its membership until an evaluation succeeds, because a failure says nothing about the answer.
  • Every other state is evaluated as a query would read it: fresh and the other stale reasons with their stored numbers, and unavailable as a missing answer. Nothing more is coming for those on its own, so waiting would wait forever.
That is why a subscription’s filter can’t read freshness: only settled answers reach it. It is also why an event’s answers are usually fresh. They can be stale when nothing is coming to refresh them, as for a periodic or manual judgment, and an answer named only in include, which the filter doesn’t read, is sent as it stands, pending included. To act only on fresh answers, check freshness in the event.

Freshness policies

A judgment’s policy decides when its answers are computed. It is a setting: changing it creates no new version. Any policy can set debounce_ms. A document that changed more recently than that is not judged until it settles, so a burst of writes costs one evaluation. Any policy can also set max_wait_ms, the ceiling: a document that never settles is still judged once that long has passed since its oldest unjudged change. It defaults to 12 × debounce_ms for a judgment with related documents and a debounce_ms above 0, and to none otherwise. Rapid writes to one document also coalesce: twelve changes in a second are judged once, on the latest revision. A get of a document with on_read judgments starts their evaluation. The first read returns them pending, unless it passes wait_ms. While judging is paused, a read starts nothing: an on_read answer reads stale if the document has an older one, and unavailable if it has none. See choosing a freshness policy for the cost of each.