Skip to content

Evaluation model

Evaluating a flag means taking a context and a flag’s rules and producing a value: run the targets, then the targeting rules in order, then the environment default. feat runs the exact same algorithm everywhere. What changes by SDK is where it runs.

There are two models, split by trust:

  • Local evaluation (server SDKs) - the SDK holds the whole datafile and evaluates in-process.
  • Remote evaluation (client SDKs) - the SDK sends the context to feat’s edge, which evaluates and returns only the resolved values.

Your targeting rules and segment definitions are part of your product logic. A datafile spells out, in plain JSON, every rule, every segment, and every attribute you target on. That is fine on a server you control. It is not fine in a web bundle or a mobile binary, where anyone can open dev tools or unzip the app and read it.

So the line is drawn at trust:

  • A server is trusted. Give it the whole datafile; let it evaluate locally with zero per-read latency.
  • A browser or phone is not. Never send it the rules. Send up the context, evaluate on the edge, send back only the answer for that one context.

This is the same split LaunchDarkly and other mature platforms make, for the same reason. The client learns the values it is allowed to see and nothing about how they were derived.

Used by @feathq/js-sdk, Go, Python, and Ruby, all with a server key.

  1. On start the SDK fetches the environment’s datafile from feat’s edge and keeps it in memory.
  2. It polls for updates (default 30s). Unchanged datafiles return 304 Not Modified via If-None-Match, so an idle poll is nearly free.
  3. Every getBooleanValue(...) runs the engine against the in-memory datafile. No network call, no latency, works during a feat outage as long as the process is up.

The context never leaves your machine, because the machine has everything it needs to evaluate.

Used by the browser SDK and the Flutter / Dart SDK, with a client-side ID or mobile key.

  1. You set a context on the client. The SDK sends it to feat’s edge.
  2. The edge evaluates every flag against that context and returns a snapshot of resolved values: value, variationId, and reason per flag. No rules, no segments.
  3. The SDK caches that snapshot, so your getBooleanValue(...) reads are still synchronous and in-process, exactly like a server SDK. The difference is only in how the snapshot was produced.
  4. The SDK keeps the snapshot fresh over a Server-Sent Events stream: the edge pushes a new snapshot whenever the flag config or the context changes, and the SDK fires a change event so your UI can re-render in milliseconds. A slow background poll runs as a safety net.

When the context changes (a user logs in, a plan upgrades) the SDK re-sends it and gets a fresh snapshot. The client only ever holds resolved values for the contexts it has actually evaluated.

Remote evaluation still lets you render correct values on the first paint. Evaluate the incoming request’s context on your server, hand the resulting snapshot to the client SDK as its bootstrap, and the first client render is correct with no round trip and no flash of defaults. See Browser SDK: server-side rendering.

The API key type decides the model, and the edge enforces it:

Key typePrefixModelReceives the datafile?
Server keyfeat_sdk_…LocalYes
Client-side IDfeat_cs_…RemoteNo
Mobile keyfeat_mob_…RemoteNo

A client-side ID or mobile key that asks for the datafile is refused; it must use the evaluation endpoint. There is no configuration that hands rules to a client key.

Local or remote, every SDK evaluates with the same reference engine (@feathq/feat-eval). The same context, the same flag, and the same underlying config always produce the same value and reason, regardless of language or where the code runs. Moving a flag read from a server to a browser does not change its result, only where the computation happens.

  • Rules and segments stay on feat’s edge for client SDKs. They are never in a bundle, in localStorage, or on a phone. Only server keys, which you keep secret, ever receive them.
  • Contexts from server SDKs never leave your machine. Contexts from client SDKs are sent to the edge to evaluate; feat counts the unique context toward your monthly active users but does not store the context or the evaluation, and there is no per-evaluation event log. See Audit log.
  • Availability. Server SDKs keep serving from their in-memory datafile through a feat outage. Client SDKs serve the last cached snapshot (and, with the optional persistent cache, the last snapshot from a previous session) until the edge is reachable again.