Prompt and context
This question isolates the feature flag evaluation hot path. Administration, approvals, and the broader platform belong to a separate design problem. Configuration propagates asynchronously and callers use SDKs in several languages, yet a user should receive an explainable, reproducible variant. Assume server-side, in-process evaluation with attribute rules and percentage rollouts.
What the interviewer evaluates
- Separating eventual configuration convergence from stable bucketing for one identity.
- Defining one
targetingKey, normalization contract, and hash algorithm across SDKs. - Switching immutable, monotonically versioned snapshots instead of exposing partial updates.
- Returning a safe default for missing context, type errors, unknown flags, and stale configuration.
- Proving consistency with golden vectors, shadow evaluation, and distribution metrics.
Clarifications before answering
Ask whether stability must hold across devices, regions, and SDK languages; how anonymous identities persist; and whether users already inside a 10% rollout must remain included when it grows. Also establish which targeting attributes are sensitive, the tolerated propagation window, and whether an emergency off switch overrides ordinary rollout rules.
A 30-second answer framework
I would compile rules into immutable, versioned snapshots and evaluate them inside each SDK. Percentage allocation encodes targetingKey, flagKey, and the seed as a length-framed canonical tuple before hashing into fixed ranges. For an ordinary change, distribute an inactive snapshot, wait for every serving region to report readiness, then advance one control-plane assignment generation. Each session or durable identity carries that generation, and serving instances retain both snapshots for a bounded overlap, so local clock skew cannot move a user between rule versions. Missing context, invalid rule types, or stale configuration return the caller's default with a reason code. Cross-language golden vectors and shadow evaluation verify identical decisions.
Step-by-step deep dive
Start with the input contract. Every server-side evaluation needs a non-empty targetingKey. Anonymous traffic can use a persisted random identifier, but not a fresh value per request. Specify string encoding, case, whitespace, number, and timestamp normalization. Hash a versioned, length-prefixed UTF-8 tuple rather than raw concatenation or delimiter-only framing; otherwise field boundaries and delimiter characters remain ambiguous across SDKs.
A bucket function can be bucket = hash(encodeTuple(v, seed, flagKey, targetingKey)) mod 100000. Each variant owns a non-overlapping contiguous range. Growing 10% to 20% expands the target range, preserving the original users. Including flagKey prevents unrelated flags from selecting perfectly correlated samples. Changing the seed deliberately reshuffles users and therefore requires an audited release.
Rule matching and bucketing must see one immutable snapshot. The distributor sends every serving region a complete inactive snapshot with checksum and monotonic version. After all regions validate and acknowledge readiness, the control plane advances one authoritative assignment generation. A session token or durable identity record carries that generation; every region evaluates the exact referenced snapshot and retains the previous snapshot until the assignment lifetime expires. Instances missing the referenced version stop serving that assignment. This protocol relies on version transport rather than synchronized clocks. An emergency kill switch may explicitly override stickiness for safety while remaining a recorded versioned rule.
OpenFeature's evaluation contract lets callers supply a default value and associates error reasons with failed evaluation. Distinguish missing flags, type mismatch, absent targeting keys, and a provider that is not ready. Keep metrics low-cardinality and do not place email addresses, device identifiers, or full evaluation context in routine logs.
Verification has three layers. Every SDK runs the same golden inputs and expected variants, including empty values, delimiters, Unicode, and field-boundary collision cases. Before replacing an evaluator, shadow both engines against production-shaped snapshots and rehearse a region that misses readiness. In production, monitor variant share, default-value rate, snapshot age, and version distribution by region. A distribution anomaly is a signal; an individual decision must still be reproducible from snapshot version, rule ID, and bucket.
Strong sample answer
Each SDK evaluates only a validated snapshot. The request supplies a stable targetingKey; the SDK hashes a versioned, length-framed tuple of seed, flagKey, and targetingKey into one of 100,000 fixed buckets. Increasing exposure only widens the range, so existing members do not fall out.
Ordinary changes reach every region before the control plane advances the assignment generation. The session or durable identity then carries that generation, and each region keeps the referenced snapshot for the assignment lifetime. Cross-region requests therefore evaluate one rule version without relying on synchronized clocks. Instances missing that snapshot stop serving the assignment. SDKs reject regressions and return the caller's default for stale configuration or invalid context. Emergency shutdown explicitly overrides ordinary stickiness and converges first.
Common mistakes
- Calling a remote flag service for every evaluation and coupling request availability to it.
- Using a language runtime's built-in hash, which may differ across processes or SDKs.
- Hashing only the user ID, creating correlated samples across all flags.
- Updating configuration field by field, exposing mixed rule and weight versions.
- Randomly assigning requests when
targetingKeyis missing. - Logging full evaluation context and leaking sensitive attributes.
Follow-up questions
Can different configuration versions be globally consistent?
Asynchronous distribution alone cannot promise a zero-width global consistency window. An ordinary change first passes readiness in every serving region; the control plane then advances one assignment generation, which the session or durable identity transports on every request. Regions retain the referenced snapshot until that assignment expires, and an instance missing it leaves the serving path. An emergency off switch may override stickiness, favor fast convergence, and monitor lagging instances.
What should identify an anonymous user?
Use a client-persisted random anonymous ID and document that clearing storage or changing devices causes reassignment. IP addresses are shared, unstable, and carry additional privacy concerns.
How do you change the hash algorithm safely?
Version the algorithm and seed in the snapshot, then shadow-compute old and new buckets to measure movement. Preserve assignments through a transition mapping when stickiness is required. If reshuffling is acceptable, still release it explicitly with a rollback snapshot.
How do you detect a faulty SDK implementation?
Run identical golden vectors in every SDK and report low-cardinality algorithm version, snapshot version, and aggregate variant counts. Freeze configuration upgrades for the divergent SDK, retain its last valid snapshot, and fix normalization or hashing before resuming.