targetingKey is answered for that user: AB tests, cohort rules and percentage rollouts all apply.
When the request happens
resolveBooleanEvaluation is synchronous in the OpenFeature Web SDK, so there is no point at which an evaluation could wait for a network call. The provider asks the service when something changes, and answers every evaluation from what that produced.
A targeting-key change is asynchronous -
await OpenFeature.setContext(...). An evaluation issued before that resolves is answered from the snapshot with STALE, never from the previous user’s values.What is sent
eq / neq / in, so a non-string field cannot participate in a rule. One is dropped and reported through the provider’s logger rather than stringified - a coerced value that then matches nothing is harder to diagnose than an absent one.
targetingKey travels as user_id and never also as an attribute, so a cohort rule cannot be written against an attribute the provider only sends by accident.
What each reason means
When the service is unreachable
A transport failure resolves from the snapshot withSTALE and no error message. Reporting an error there would hand back the caller’s default - false for a flag that is genuinely on - because of one failed request, which is the worst available outcome.
Previously fetched targeted values are kept rather than cleared: clearing them would turn a transient error into a visible flag flip.
When the AB Testing add-on is not active
The service answers HTTP 403, and the provider resolves from the snapshot withSTATIC, then stops asking for five minutes (addonSuppressionMs).
It is a throttle, not a latch: the window expires on its own, any success clears it immediately, and a project that buys the add-on starts getting targeted results within the window with nothing to restart.
Seeing the diagnostics
A dropped context field is reported atwarn level, which OpenFeature’s DefaultLogger (the default) already writes to the console. A failed targeted fetch and an inactive add-on are reported at debug level, which DefaultLogger discards - pass a logger that keeps debug to see them:
