Local Evaluation
Feature flag evaluation performed entirely from an in-memory snapshot with no network requests on the request path.
Introduction
Local Evaluation is the core runtime model used by SOASAP. Applications evaluate feature flags directly from memory. The SDK does not contact SOASAP Cloud during evaluation — every flag read is performed against a synchronized local snapshot held in process.
flags.GetBool("new-checkout", defaultValue: false);
The result is returned immediately from memory. No HTTP request is performed. No disk access occurs on the read path. Evaluation behaves like a dictionary lookup against the current snapshot, with your code-defined default returned when a key is missing or invalid.
This model separates evaluation (synchronous, in-process, on every request) from synchronization (asynchronous, background, over SSE). That separation is what makes SOASAP suitable for request handlers, middleware, and high-throughput services.
Why local evaluation exists
Many feature flag systems evaluate flags at request time by calling a remote control plane. The traditional architecture looks like this:
Request-time remote evaluation has predictable consequences:
- Additional latency — every flag read adds network round-trip time to the critical path
- Additional infrastructure dependency — application availability becomes coupled to the flag service
- Availability coupling — control plane outages or rate limits can degrade or block application requests
- Increased tail latency — p99 and p999 request times include remote API variance, retries, and timeouts
SOASAP avoids this model. Configuration is distributed to SDKs in the background; applications read from a local snapshot at evaluation time. The control plane is required for synchronization and dashboard management — not for serving individual flag reads.
Local evaluation flow
The SDK maintains a local in-memory snapshot for the bound environment. Every getter performs a lookup against that snapshot. Evaluation complexity is effectively O(1) — constant time regardless of how many flags exist in the project.
Examples across SDKs:
.NET
flags.GetBool("new-checkout", defaultValue: false);
Node.js
flags.getBool("new-checkout", false);
Python
flags.get_bool("new-checkout", False)
The lookup path is identical for GetString,
GetNumber, GetJson, and equivalent
methods in other SDKs. Type validation and default fallback occur in-process without I/O.
What does not happen during evaluation
Local evaluation is defined as much by what the SDK does not do on the read path as by what it does. The following operations never occur during a flag getter call:
- No network requests — evaluation does not open sockets or wait on connectivity
- No HTTP calls — no REST or polling requests to SOASAP Cloud on read
- No gRPC calls — no RPC to a remote evaluation service
- No DNS lookups — hostname resolution is not triggered per flag read
- No database queries — flag values are not fetched from a datastore at read time
- No disk reads — the hot path reads from memory only; persistent cache is loaded at startup, not on each getter
- No cache misses that trigger external requests — a missing key returns your code default; there is no lazy fetch to the control plane
- No synchronization waits — getters never block on SSE, reconnect, or sync completion
Each omission removes a source of latency variance and failure from the request path. Evaluation time is bounded by in-process memory access and type coercion — not by network conditions or upstream service health.
Background synchronization may read from or write to disk independently of evaluation. See Persistent Cache.
Runtime architecture
SOASAP Cloud is the control plane. It stores flag definitions, environment bindings, and audit history. When configuration changes, deltas are pushed to connected SDKs over Server-Sent Events (SSE).
SDKs synchronize in the background — connecting on startup, applying deltas, and reconnecting with backoff after disconnects. Applications evaluate locally against the snapshot the SDK holds in memory at the moment of the read.
Synchronization and evaluation are separate concerns. A slow or failed sync does not block evaluation; evaluation does not trigger synchronization. This boundary is intentional and applies across all supported SDK platforms.
See Real-Time Synchronization.
Latency characteristics
Local evaluation provides predictable latency. Evaluation time is independent of:
- Internet connectivity at the moment of the read
- SOASAP Cloud availability or regional deployment status
- API response times, rate limits, or quota on the control plane
- Regional network latency between your application and SOASAP infrastructure
In practice, flag reads behave similarly to reading from a local dictionary or hash map. Adding ten flag checks to a request handler adds microseconds of in-process work — not ten network round trips. Tail latency for flag evaluation is not coupled to control plane p99.
Compare this to remote evaluation where each read may add 1–50+ ms depending on network conditions, and where timeout/retry policies can push tail latency into hundreds of milliseconds.
Resilience benefits
Because evaluation does not depend on live connectivity to SOASAP Cloud, applications remain able to read flags during infrastructure and network failures. Only synchronization is affected in these scenarios — the last known snapshot (or code defaults) continues to serve reads.
SOASAP Cloud outage
Evaluation continues using the in-memory snapshot. Connected SDKs stop receiving deltas until the control plane recovers; reads are unaffected. New processes without cache use code defaults until sync resumes.
Internet connectivity loss
Evaluation continues. SSE disconnects in the background; the snapshot in memory remains readable until the process restarts without a persistent cache.
SSE disconnect
Evaluation continues using the last known snapshot. The SDK reconnects asynchronously with backoff. Dashboard changes are not reflected until reconnect and delta delivery — but existing flag values remain available locally.
Control plane maintenance
Evaluation continues. Maintenance windows affect synchronization and dashboard access, not in-process reads against the current snapshot.
See Offline Operation.
Performance characteristics
Flag reads are designed for use in latency-sensitive code paths:
- Request handlers — HTTP middleware, API controllers, route handlers
- Middleware — authentication gates, routing, feature branching per request
- Background jobs — workers and schedulers that branch on configuration
- Hot loops — tight iteration where per-item remote calls would be prohibitive
- High-throughput services — services where flag checks occur on every request at scale
Evaluation complexity: O(1)
Each getter performs a constant-time key lookup in the in-memory snapshot. Reading one flag or one hundred flags in a handler does not change the per-read cost — only the number of lookups. There is no linear scan of the full flag set and no remote batching requirement.
Reuse a single SDK client instance per process. Constructing multiple clients duplicates snapshots and background sync workers without benefit.
Relationship to other features
Local evaluation is the foundation. Other SOASAP architecture features exist to keep the snapshot current, durable, and safe — not to participate in the read path.
| Feature | Role | Read path impact |
|---|---|---|
| Real-Time Synchronization | Pushes configuration deltas over SSE so the snapshot stays current after dashboard changes | None — runs in background |
| Persistent Cache | Restores the last snapshot from disk on cold start before SSE connects | None — hydration occurs at startup, not per getter |
| Offline Operation | Defines behavior when sync is unavailable — last snapshot or defaults | None — same O(1) memory lookup |
| Default Values | Provides safe fallback when a key is missing, invalid, or not yet synchronized | Returned in-process when lookup fails |
| Non-Blocking Startup | Starts SSE and cache hydration without blocking host startup or health checks | None — first reads use cache or defaults immediately |
Together, these components implement a local-first configuration model: evaluate from memory on every read; synchronize and persist in the background.
Common misconceptions
"Every flag read calls SOASAP"
False. Flag reads never contact SOASAP Cloud. Only background SSE synchronization communicates with the control plane. Logging, metrics, and dashboard edits are separate from evaluation.
"The SDK must be online to evaluate flags"
False. Evaluation requires an in-memory snapshot or a code default — not live connectivity. Offline processes continue reading the last synchronized snapshot until restart without cache.
"Flag evaluation depends on SOASAP API latency"
False. API latency affects synchronization timing, not getter latency. A slow or unavailable API does not add milliseconds to individual flag reads.
"The SDK reads from disk on every request"
False. Persistent cache is loaded into memory at startup (or hydrated asynchronously on some platforms). Per-request getters read from the in-memory snapshot only.
"Missing flags trigger a fetch from the server"
False. A missing or unknown key returns the explicit default you pass to the getter. There is no lazy load or just-in-time sync on the read path.
Production recommendations
- Evaluate flags freely inside request handlers — local evaluation is designed for the hot path; do not batch or cache flag results in application code unless you have a measured need.
- Reuse a single SDK instance — one client per process shares one snapshot and one background sync worker; multiple instances waste memory and connections.
- Enable preload where supported —
PreloadFlags()(.NET),preloadFlags = true(Kotlin), orpreload: true(Node, Python, mobile) starts background sync without blocking startup. See Preload Flags. - Always provide explicit defaults — defaults define behavior when the snapshot is empty, stale, or missing a key; they are part of production safety, not optional parameters.
- Monitor synchronization health separately from application health — use
onError/OnErrorhandlers and SSE disconnect alerts; a healthy app can serve stale flag values while sync is degraded.
Related documentation
- Real-Time Synchronization — SSE pipeline from SOASAP Cloud to the local snapshot
- Persistent Cache — cold-start snapshot restoration without blocking evaluation
- Offline Operation — evaluation behavior during outages and disconnects
- Default Values — code-defined fallbacks when the snapshot cannot supply a valid value
- Non-Blocking Startup — startup flow that preserves local evaluation from the first request
- Production Safety — kill switches, defaults, and environment isolation
- SDK Documentation — install and configure your platform SDK