A feature flag check often sits in a hot path — inside a request handler, a render, a loop. How that check is implemented decides whether feature flags cost you nothing or cost you a network round-trip every time. This post is about local evaluation: what it means, why it matters, and where it bites.
Two ways to evaluate a flag
Remote evaluation: your code asks the flag provider “is new-checkout on for this user?” over the network. The provider runs the targeting rules and returns the answer. Simple, but every check is an HTTP request — latency, a failure mode, and a rate limit in your critical path.
Local (in-SDK) evaluation: the SDK downloads the entire flag configuration for your environment once, holds it in memory, and evaluates rules itself. A flag check is a function call against an in-memory structure — no network, sub-microsecond, no failure mode.
How local evaluation works
The lifecycle is small:
- Initialize. On startup the SDK fetches the full ruleset for its environment API key and builds an in-memory index. Your app waits for this once.
- Evaluate.
getBooleanFlag('key', default, context)walks the cached rules for that flag against the supplied user context and returns a value. No I/O. - Refresh. A background task polls for changes (ToggleTown defaults to every 30 seconds) or holds a streaming connection. When the config changes, the in-memory copy is swapped atomically.
- Shut down. The SDK stops the refresh task cleanly so your process can exit.
Because every SDK ships the same rule evaluator, a flag resolves to the same value whether it is checked from Node, Python, or Go — the server is not in the loop.
Why it matters: latency
If a flag check is a network call and you check three flags while rendering a page, you have added three round-trips to that page. Teams work around this by caching responses, which means writing a cache, an invalidation strategy, and a stampede guard. Local evaluation is that cache, built into the SDK, kept fresh for you.
Why it matters more: resilience
This is the part people underrate. With remote evaluation, the flag provider is a hard dependency of your request path. If it is slow or down, your app is slow or down — unless you have carefully implemented timeouts and fallbacks everywhere.
With local evaluation, a provider outage is a non-event for running processes. Your SDK keeps serving flags from its last-known config. The worst case is that a flag change you made during the outage does not propagate until the provider recovers. Your users never see an error because a flag service had a bad day.
A good SDK makes this explicit: it exposes whether its config is stale and fires a callback so you can alert on “flags have not refreshed in N minutes” without it ever affecting evaluation.
The trade-offs
- Propagation delay. A change takes up to one poll interval to reach each SDK (seconds, not instant). Streaming shrinks this to near-real-time at the cost of a persistent connection. For most rollouts, 30 seconds is invisible.
- The whole ruleset is in memory. Fine for hundreds or low thousands of flags; something to think about at extreme scale.
- Client-side exposure. In a browser or mobile app, shipping the full ruleset can leak the existence of unreleased features. Server-side SDKs do not have this problem; client SDKs should receive a pre-evaluated or filtered payload.
- Initialization is a step. Your app has to wait for the first config fetch, or evaluate against defaults until it arrives. Both are fine as long as you choose deliberately.
What to look for in an SDK
- Local evaluation by default, not as an add-on proxy you have to run.
- A clear stale-config signal and callback.
- Sensible behavior before initialization completes (return your supplied default).
- Consistent bucketing for percentage rollouts across every language.
- Clean shutdown so serverless and short-lived processes behave.
Every ToggleTown SDK — JavaScript, React, Node.js, Python, Go — evaluates locally, exposes staleness, and shares one rule evaluator. It is also why adding a flag service does not add a new way for your app to fall over. For the wider question of when a service is worth it at all, see feature flags vs environment variables.