# Snapshots and configuration freshness

Understand ETags, polling, invalidation, stale snapshots, and consistency.

Snapshot evaluation trades immediate hosted freshness for low-latency in-process decisions and
resilience. One snapshot contains active typed flags and ordered rules for one project environment.

Use snapshots only in trusted server processes. They include server-only values and targeting
configuration and must never be exposed to browsers.

<FlowDiagram
  ariaLabel="Snapshot refresh flow"
  items={[
    "Configuration change",
    "Snapshot version",
    "ETag poll",
    "In-memory replacement",
    "Local evaluation",
  ]}
/>

## Fetch the first snapshot

`GET /v1/snapshot` requires a server runtime key with `runtime:snapshot`. The key fixes the project
and environment; no URL parameter can redirect the request to another boundary.

Validate the complete response before replacing application state. A partial or malformed snapshot
must not displace a last-known-good configuration.

The Node.js SDK performs this validation during `initialize()`. Initialization rejects when the key,
request, or snapshot is invalid unless the application operates from bootstrap data only.

## Poll with ETags

The snapshot response includes an `ETag`. Send it in `If-None-Match` on the next poll. An unchanged
snapshot returns `304` without another response body.

The Node.js SDK polls every 30 seconds by default. It replaces in-memory state only after a successful,
validated response.

Call `refresh()` when an immediate check is justified, such as after an operator-controlled change in
a deployment or incident workflow. Do not refresh before every evaluation.

## Consistency expectations

Snapshot clients are eventually consistent with hosted configuration. Different processes can briefly
hold different versions because they poll at different times or experience different network failures.

Do not assume a console save is visible to every process immediately. For urgent changes, verify
refresh health in application telemetry and understand the maximum tolerated staleness.

Direct HTTP evaluation uses current hosted configuration and avoids polling delay, but introduces a
network dependency for every request.

## Invalidation is advisory

`GET /v1/snapshot/stream` is a Server-Sent Events invalidation channel. It tells a consumer that a new
snapshot may exist. It does not carry authoritative flag configuration.

Streams can disconnect, duplicate notifications, or arrive after a poll. A consumer must fetch the
snapshot and continue ETag polling as its source of truth.

The released Node.js SDK uses polling and does not consume the stream. Do not document or depend on
stream behaviour through that package.

## Stale but available

After one successful load, a background refresh failure leaves the last snapshot available. This
prevents a temporary control-plane outage from becoming an application outage.

The tradeoff is stale configuration. Report background failures through `onError`, monitor their
duration, and alert when staleness exceeds the application's operational tolerance.

Before the first successful load, only bootstrap flags or caller defaults are available. Decide
explicitly whether startup should fail, continue in a degraded state, or wait and retry.

## Bootstrap data

Bootstrap flags can make a client ready immediately and support offline tests. When a runtime key is
also present, a later successful refresh replaces the bootstrap state.

Treat production bootstrap data as code-owned configuration. Review its age, safe defaults, and
deployment lifecycle. Do not let an old embedded snapshot become an unnoticed permanent source.

## Diagnose freshness

- **A change is not visible:** wait for the poll or call `refresh()` once.
- **One process differs:** compare refresh success and snapshot version across processes.
- **Repeated `304`:** the hosted snapshot has not changed for that key-bound environment.
- **Stream connected but values stale:** fetch the authoritative snapshot and inspect polling.
- **Refresh fails but evaluation works:** the process is using its last successful snapshot.

Related pages: [Node.js SDK](/docs/sdk/node),
[Errors and fallbacks](/docs/evaluate/errors-and-fallbacks), and the generated
[snapshot reference](/docs/api/reference/runtime/snapshot).
