Concepts

Local Evaluation and the CDN

Understand how SDKs fetch the environment payload once, cache it, and evaluate rules locally — and what that means for latency, resilience, and the telemetry Zenmanage collects.

SDKs cache once, then evaluate locally

When an SDK starts up, it fetches the environment's full flag payload from the CDN — every flag, value, and targeting rule your key is scoped to, in one request. From then on the SDK holds that payload in memory and evaluates each flag against it locally. There is no network round trip per flag read: matching selectors, walking rule priority, and resolving the final value all happen in-process.

That's the whole reason evaluation is fast — ~1ms locally instead of the round-trip latency of a network call — and it's also a resilience property. If Zenmanage is briefly unreachable, an SDK that already loaded a payload keeps evaluating against the copy it has. Only an SDK that has never successfully fetched a payload falls back to the default value your code supplies at the call site.

This is the SDK model, not the direct API model

Calling the public API directly is different: GET /v1/flags evaluates against your context on the server, per request. There's no local cache to reason about, but you take on the latency and availability of a network call for every read.

Three events, three different signals

This model produces three distinct telemetry events. They sound similar but answer different questions, and mixing them up is the most common source of confusion when reading evaluation data:

Event What it means When it fires
Payload retrieved An SDK fetched the environment's flag payload from the CDN. On SDK startup, and again whenever it refreshes its cached payload. This fetch covers every flag in the environment, regardless of whether your code reads it.
Flag evaluated A specific flag was evaluated server-side. When something calls the public API directly — GET /v1/flags or GET /v1/flags/{flag-key} — instead of reading from an SDK's local cache.
Flag used An SDK is reporting back that your code actually evaluated this flag locally. Automatically, when usage reporting is enabled and your application calls the flag. The same signal is available directly via POST /v1/flags/{flag-key}/usage for integrations that evaluate flags themselves.

Retrieved vs. used: the gap that matters

Because a payload contains every flag in the environment, a flag rides along in every retrieval as long as any SDK is connected — that's true whether your code checks it or not. Used only fires when your code actually calls the flag. A flag can be continuously retrieved for months after every call site referencing it was deleted, and retrieval alone would never tell you that.

That gap between the two signals is exactly what powers stale-flag detection: staleness is measured against use, not retrieval, because retrieval only proves an SDK is connected. See Flag Lifecycle and Status for how the Stale Flags report and alert thresholds are built on top of this. The same per-flag freshness signals — Last Retrieved, Last Used, and Last Updated — are what you're looking at when you check the timestamps on an individual flag's detail view.

Watching it happen in the Debug console

The Debug console's live event stream shows these three events as they happen, so you can watch payload retrievals, server-side evaluations, and usage reports arrive in real time instead of inferring them from downstream reports. It's the fastest way to confirm an SDK actually connected and is reporting usage the way you expect.

The per-context evaluation view answers a narrower question: for one specific context, what does a flag resolve to right now, and which rule produced that result? Because that view runs the same evaluation your SDKs run locally, it's the tool to reach for when a rollout looks right in the rule builder but a real context isn't seeing the value you expect.

Start with context, not rules

Most evaluation surprises turn out to be a context problem — a missing attribute or the wrong identifier — rather than a rule problem. The Debugging and Observability guide walks through the full triage sequence.

Where to go next

See the SDKs page for what local evaluation and usage reporting look like in each language. For designing your integration around brief outages, see Reliability and Operations. To triage a specific bad evaluation, start with the Debugging and Observability guide.