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.
Why there are two
Section titled “Why there are two”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.
Local evaluation (server SDKs)
Section titled “Local evaluation (server SDKs)”Used by @feathq/js-sdk, Go, Python, and Ruby, all with a server key.
- On start the SDK fetches the environment’s datafile from feat’s edge and keeps it in memory.
- It polls for updates (default 30s). Unchanged datafiles return
304 Not ModifiedviaIf-None-Match, so an idle poll is nearly free. - 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.
Remote evaluation (client SDKs)
Section titled “Remote evaluation (client SDKs)”Used by the browser SDK and the Flutter / Dart SDK, with a client-side ID or mobile key.
- You set a context on the client. The SDK sends it to feat’s edge.
- The edge evaluates every flag against that context and returns a snapshot of resolved values:
value,variationId, andreasonper flag. No rules, no segments. - 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. - 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
changeevent 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.
Server-side rendering
Section titled “Server-side rendering”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.
Which model each key uses
Section titled “Which model each key uses”The API key type decides the model, and the edge enforces it:
| Key type | Prefix | Model | Receives the datafile? |
|---|---|---|---|
| Server key | feat_sdk_… | Local | Yes |
| Client-side ID | feat_cs_… | Remote | No |
| Mobile key | feat_mob_… | Remote | No |
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.
Same engine, same result
Section titled “Same engine, same result”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.
What this means for your data
Section titled “What this means for your data”- 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.
Related
Section titled “Related”- SDKs overview - the per-runtime table.
- API keys - what makes each key type safe.
- Datafile format - the JSON that server SDKs evaluate against.
- Evaluation order - the algorithm both models run.