Evaluate in your application
OpenFeature providers
A Featurevisor provider lets an application that already uses OpenFeature evaluate Featurevisor through the OpenFeature API. Providers are optional, and every SDK works without one. Choose one when your code already calls OpenFeature, such as while moving from another flagging service, so those calls stay as they are.
Choose a provider#
| Platform | Provider documentation |
|---|---|
| Node.js | Node.js provider |
| Browser | Browser provider |
| Go | Go provider |
| Swift | Swift provider |
| Java | Java provider |
| Kotlin | Kotlin provider |
| Ruby | Ruby provider |
| Python | Python provider |
| PHP | PHP provider |
| Rust | Rust provider |
| Elixir | Elixir provider |
Flag keys#
OpenFeature has one kind of key, while Featurevisor has flags, variations and two kinds of variable. Providers tell them apart by the key:
| OpenFeature key | Reads |
|---|---|
checkout | The flag of checkout |
pricing:variation | The variation of pricing |
buyButton:label | The feature variable label |
variable:supportEmail | The global variable supportEmail |
Call the resolver that matches the value's type: boolean for flags and boolean variables, string for variations and string variables, the platform's number resolvers for numbers, and object for arrays, objects and json.
The key is split at the first :. A feature key comes first, unless the key starts with the reserved variable prefix, which selects a global variable. If the separator, the variation selector or the variable prefix clashes with your keys, every provider lets you change them. The provider pages give the option names for each language.
Evaluation context#
The provider copies OpenFeature's evaluation context into Featurevisor, without changing it. The targeting key becomes userId, the attribute features usually bucket by. If your features bucket by another attribute, set the provider's targeting key field to it.
In Node.js, pass a string targeting key and your attributes:
const context = { targetingKey: 'user-4', country: 'nl',}const enabled = await client.getBooleanValue( 'checkout', false, context,)Featurevisor sees userId: 'user-4' and country: 'nl', so the new checkout is enabled. See the Node.js provider for setup.
OpenFeature still merges contexts and runs its hooks, and Featurevisor still runs its modules. Neither is translated into the other.
Resolution details#
Providers return the OpenFeature default value when a feature is missing, a value has the wrong type, or evaluation fails. They map evaluation details to these OpenFeature fields:
| Featurevisor result | OpenFeature result |
|---|---|
| Forced, sticky or rule match | TARGETING_MATCH |
| Unmet feature or variable prerequisites | DISABLED |
| Variation allocated by bucketing | SPLIT |
| Disabled result | DISABLED |
| Normal default or no match | DEFAULT |
| Missing feature or variable | ERROR with FLAG_NOT_FOUND |
Variation requested for a feature without variations (no_variations) | ERROR with FLAG_NOT_FOUND |
Evaluation error (error) | ERROR with GENERAL |
| Wrong resolver type | ERROR with TYPE_MISMATCH |
| Invalid JSON or a datafile rejected by the SDK | ERROR with PARSE_ERROR |
Where the OpenFeature SDK supports it, flag metadata includes the Featurevisor reason, the feature and variable keys, the revision, the schema version and the matching rule or bucket. Variation evaluations also give the selected variation as the OpenFeature variant.
A composed global variable resolves through the existing global variable object path. Its Featurevisor reason variable_composed maps to TARGETING_MATCH. Upgrade every consumer to a v4 SDK and provider before publishing these datafiles.
Empty targeting keys#
An explicit empty targetingKey replaces the configured field with "" when it reaches the provider. Omitting it preserves that field. The Node.js and web clients preserve empty strings during context merging. Use a string as the OpenFeature contract recommends, although the JavaScript provider also accepts a finite number from untyped context.
Some clients cannot tell an empty key from a missing one:
- In Python and PHP, context merging drops an empty targeting key. Set the configured Featurevisor field itself to
""in the context attributes. - In Go, flattening leaves out an empty targeting key. Include
"targetingKey": ""in the attributes instead. - In Swift, the context getter returns an empty string for both. Set the configured Featurevisor field itself to
"".
A nonempty targeting key inherited from another context still takes precedence over the configured field in clients that drop the narrower empty key. Clear that inherited key at its source before using an attribute workaround. The native SDK pages document their exact APIs.
Tracking#
Where the platform's OpenFeature SDK supports tracking, a provider does nothing with tracking events until you give it an onTrack callback. Use the callback to forward them to your analytics. The Rust and Elixir OpenFeature SDKs do not support provider tracking yet, and their provider pages say so.
Instance ownership#
A provider either creates a Featurevisor instance from options, or uses one your application passes in.
An instance the provider creates is its own, and it closes the instance when it shuts down. An instance your application passes in stays yours. Shutting the provider down leaves it open for anything else using it, so close it once they have all finished.
If you pass both an instance and options for creating one, the instance wins. The provider's own options, for keys and tracking, still apply. Swift and PHP also have a close or shutdown method for a provider whose lifecycle your application manages. The provider pages show each language's constructor and lifecycle methods.
Initialization and recovery#
Your application fetches datafiles and supplies them to Featurevisor. The provider does not fetch them for you. Await provider registration where the platform supports it before serving evaluations.
When a provider creates its own Featurevisor instance, an invalid initial datafile marks it as unhealthy. This does not depend on the diagnostic log level, including fatal. The platform decides how that failure reaches your application:
- Node.js, browsers, Go, Java, Kotlin, Ruby and Python: registration reports an error. An accepted datafile clears it, and the provider emits readiness.
- Swift: the provider reports an error status through its event stream, and its initialization does not throw. An accepted datafile makes it emit readiness and a configuration change.
- PHP: there is no registration step, so evaluations report
PARSE_ERROR. They resume once an accepted datafile clears the error. - Rust: provider status is
Error, since initialization cannot return one, and evaluations reportParseError. An accepted datafile returns the status toReady. - Elixir: initialization returns
{:error, :parse_error}. Set a valid datafile, then initialize or register the provider again.
A rejected update does not replace the SDK's last accepted datafile, but the provider reports the datafile error until an update is accepted. While it is unhealthy, OpenFeature clients return the application's fallback. Depending on the platform and its readiness checks, the client may report a provider status error before calling the provider's resolver. Inspect evaluation details and provider events rather than treating a fallback as a configured value.
Browser and Swift providers also notify consumers when the underlying Featurevisor context or sticky state changes, including changes to a supplied instance. OpenFeature context changes still use OpenFeature's own context handling. Shutdown removes the provider's subscriptions and closes only an instance it owns.
For a supplied instance, the provider observes updates after it attaches. It does not replay errors from before it was created. The language pages document the exact registration, status, event and shutdown APIs.
Example application#
The Featurevisor OpenFeature example for Node.js is a complete application using the server provider. It loads a published datafile, evaluates through an OpenFeature client, and tests flags, variations, variables, context mapping, default values and the provider lifecycle.
Related#
- The Node.js and browser providers
- Evaluation reasons, which the result mapping follows
- SDK overview

