> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vainona.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Choosing a freshness policy

> Compute answers when documents change, when they are read, or on a schedule.

Nothing is computed continuously. An answer is computed when its policy says so and not again until the document changes. A document that sits untouched for a year costs storage only. The cost driver is changes per month, not rows, and the policy decides which changes you pay for.

## Pick by how the answer is read

| You read the answer...                                                                                  | Policy                        |
| ------------------------------------------------------------------------------------------------------- | ----------------------------- |
| In queries that filter or sort across the namespace ("every ticket over 0.85")                          | `on_change`                   |
| One document at a time, when someone opens it                                                           | `on_read`                     |
| As a prediction that goes stale with time, whether or not the document changes ("churn within 30 days") | `periodic` with an `interval` |
| Only in occasional analyses you start yourself                                                          | `manual`, with a backfill     |

* **`on_change`** is the only policy you can filter or rank on, because the query needs every answer to exist. It is also the most expensive: every change to every document is judged.
* **`on_read`** is the default. The answer is computed the first time a get or query includes it, then cached until the document changes. Cold namespaces with `on_read` judgments cost nothing until someone looks. The first read returns `pending`, unless it passes `wait_ms`.
* **`periodic`** recomputes every document whose answer is older than the interval. Over a large namespace that is a recurring backfill, billed as one. The namespace's stats show its projected monthly cost.
* **`manual`** answers change only when you run a backfill.

## Switching to `on_change`

The policy is a setting, so changing it creates no new version:

```python theme={null}
ns.judgments.update("needs_escalation", freshness={"policy": "on_change"})
```

Switching to `on_change` needs an answer for every document. Without `confirm=True` the call changes nothing and returns a backfill estimate for the documents that have no current answer, with its cost and duration. Call it again with `confirm=True` to switch and start the backfill.

For a judgment that reads [related documents](/guides/related-documents), the estimate also carries `replay`: what it would cost a month from then on, replayed from your last 30 days of writes. Creating such a judgment with `on_change` returns the same replay estimate and creates nothing until you pass `confirm=True`. See [the replay estimate](/guides/related-documents#the-replay-estimate), and what "at least" means there.

## Chatty documents: debounce

Any policy can set `debounce_ms`. A document that changed more recently than that is not judged until it settles, and then only its newest revision is judged. For live conversations, 2,000 ms turns a burst of 50 messages into one evaluation, about two seconds after the burst ends.

```python theme={null}
ns.judgments.update("needs_escalation", freshness={"policy": "on_change", "debounce_ms": 2000})
```

Rapid writes are coalesced anyway: the engine only ever sees the newest revision a worker can see. Debounce adds a deliberate wait on top.

## Documents that never settle: the ceiling

A debounce never ends for a document that changes more often than the debounce: an account whose tickets arrive every few minutes, or a conversation that never pauses. `max_wait_ms` is the ceiling. Such a document is judged once it has been quiet for `debounce_ms`, or once `max_wait_ms` has passed since its oldest unjudged change, whichever comes first.

```python theme={null}
ns.judgments.update("churn_risk", freshness={"policy": "on_change", "debounce_ms": 600000, "max_wait_ms": 3600000})
```

With a 10-minute debounce and a 1-hour ceiling, a burst of 100 writes in 5 minutes costs one evaluation, and a document written every minute for 3 hours costs 3.

* **Defaults.** For a judgment with [related documents](/guides/related-documents) and a `debounce_ms` above 0, the ceiling defaults to 12 × `debounce_ms`; with no debounce there is nothing to wait for, so there is no ceiling. For any other judgment it defaults to none, so a debounce behaves as it always has. `GET` returns the value in effect.
* **Bounds.** It must be at least `debounce_ms`. `null` means no ceiling.
* **A setting.** Like the debounce, changing it creates no version. A lower ceiling means fresher answers and more evaluations.

For a judgment with related documents, "changes" includes writes to the documents that point at the judged one, so the ceiling is what keeps a busy account's answer from lagging for ever. Its answer lags by the debounce, typically minutes, and at most by the ceiling.

## Fan-out: when a referenced document changes

A judgment can read the one document each judged document points at: its [referenced document](/guides/context-recipes#the-document-the-judged-one-points-at). A change to what the relation shows of it re-judges every judged document that points at it and is inside the **re-judge scope**. That is a fan-out, and `freshness.fanout` decides which judged documents it re-judges and when. Like the rest of `freshness`, these are settings: a `PATCH` changes the keys it sends, merges `scope` per key, and creates no version.

```python theme={null}
ns.judgments.update("needs_review", freshness={"fanout": {"scope": {"created_within": "30d", "where": {"attributes.status": "open"}}}})
```

| Setting                | Default                    | What it does                                                                                                                                                            |
| ---------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scope.created_within` | `"30d"`                    | Re-judge only judged documents created no more than this long before the change. `null` means all of them                                                               |
| `scope.where`          | none                       | Narrow the scope to judged documents whose attributes match, in the shape of `applies_to`. `null` removes it                                                            |
| `debounce_ms`          | 600,000 (10 minutes)       | Fan out once the referenced document has had no change for this long, so a burst of changes costs one fan-out                                                           |
| `max_wait_ms`          | 6 × `debounce_ms` (1 hour) | Fan out a referenced document that keeps changing once this long has passed since its oldest change not yet fanned out. At least `debounce_ms`; `null` means no ceiling |
| `job_above`            | 10,000, or the namespace's | A fan-out of more judged documents is a `fanout` job with an estimate. `0` makes every fan-out a job. `null` follows the namespace's again                              |
| `confirm_jobs`         | `true`, or the namespace's | A `fanout` job waits for your confirm. `false` starts it at once, unless it does not fit the budget. `null` follows the namespace's again                               |
| `auto_daily_limit`     | 100,000                    | The most judged documents this judgment's fan-outs re-judge automatically in any 24 hours; past it, a fan-out waits for confirm. `null` means no limit                  |

* **The scope counts from the change,** not from now, so one change's scope stays fixed however long its job waits. A judged document outside it keeps its answer and its freshness; its watermark says which version of the referenced document it read, and its next own write re-judges it.
* **Only a change to what the relation shows counts.** An edit to a field it leaves out, or a move inside a [band](/guides/context-recipes#bands), neither fans out nor starts the debounce.
* **The fan-out debounce is its own.** The judgment's `debounce_ms` and `max_wait_ms` still govern the judged documents' own writes, so a new judged document is judged within seconds.
* **Only `on_change` fans out.** Under the other policies a change makes the in-scope answers `stale`.
* **The namespace** sets `share`, the most of its in-flight engine requests fan-out may use (half by default), and the `job_above` and `confirm_jobs` its judgments follow unless they set their own. See [namespaces](/concepts/namespaces#settings).

In-scope answers are `pending` from the change until they are re-judged, including while a `fanout` job waits for confirm, and `stale` if you cancel it. [Judge a document with the document it points at](/guides/referenced-document#the-controls-in-order-of-effect) works through what each setting saves.

## Budgets

A namespace budget caps judgment compute per month. When it is reached, evaluation pauses and answers go `stale` rather than overspending. Writes continue, unless the budget says `"on_exceeded": "reject"`. Every backfill is checked against the remaining budget before it starts. See [namespaces](/concepts/namespaces#settings).
