OpenFeature compatibility
OpenFeature is a vendor-neutral API for reading feature flags. Your application code calls client.getBooleanValue(...), and a provider underneath decides where the answer comes from.
This page is the honest state of that support. The working code, with imports you can copy, is on the OpenFeature integration page.
What ships today
For JavaScript and TypeScript, two adapter classes on one entry point:
| Adapter | Entry point | Wraps |
|---|---|---|
AvsbProvider | @avsbhq/utils/openfeature | AvsbServer from @avsbhq/node |
AvsbWebProvider | @avsbhq/utils/openfeature | AvsbClient from @avsbhq/browser |
@avsbhq/utils arrives with @avsbhq/browser and @avsbhq/node, so there is nothing extra to install.
Every server SDK in another language ships its own provider, from version 1.0.1. You install the OpenFeature SDK for your language next to it:
| Language | Provider |
|---|---|
| Python | AvsbOpenFeatureProvider from avsb.openfeature_provider, installed with pip install "avsb[openfeature]" |
| Go | NewProvider(server) from github.com/avsbhq/avsb-go/openfeature |
| .NET | AvsbOpenFeatureProvider in Avsb.SDK, for OpenFeature .NET 2.0 or later |
| Java | com.avsbhq.avsb.OpenFeatureProvider |
| Ruby | Avsb::OpenFeatureProvider |
| PHP | Avsbhq\Avsb\OpenFeatureProvider |
Each SDK's README has the setup code. Version 1.0.1 of these SDKs is on its way to its registry with this release.
That is the whole list. There is no published @avsbhq/openfeature package, no hosted OFREP endpoint, and no OpenFeature conformance suite in our CI. If a page or a changelog told you otherwise, it was wrong.
Two properties of the adapters are worth knowing before you wire either one up:
- They do not import the OpenFeature packages. They are written against the shapes OpenFeature defines, so installing
@avsbhq/utilsnever pulls an OpenFeature SDK into your build. In practice TypeScript is then comparing two independent declarations of the same shape and can reject the handoff. The fix is a short wrapper class, which the integration page gives you in full. - Resolution is synchronous in both. That matches the OpenFeature web SDK, which resolves synchronously. The OpenFeature server SDK expects providers to resolve asynchronously, which is most of what that wrapper is doing.
What the OpenFeature API can carry
| OpenFeature | A vs B | Notes |
|---|---|---|
targetingKey | context.key | The bucketing identifier. |
| Any other context property | A targeting attribute | Attached to a user kind context. |
| Multi-kind context | Not expressible | The adapter always builds a single user context. |
ResolutionDetails.value | Flag.value | |
ResolutionDetails.variant | Flag.variationKey | undefined when the default was served. |
ResolutionDetails.reason | Flag.source, upper-cased | RULE, HOLDOUT, BANDIT, STICKY, DEFAULT, and so on. These are the A vs B sources upper-cased whole, not OpenFeature's standard reason strings. |
flagMetadata | ruleId, ruleType, durationMicros | |
errorCode | Set for the two error sources | A missing flag, or one whose declared type contradicts the getter you called, resolves as reason: 'ERROR' with errorCode: 'FLAG_NOT_FOUND'. Reading before the SDK is ready gives PROVIDER_NOT_READY. Your default is returned in both cases. |
| Provider hooks, events, status | Not implemented |
The typed getters are honoured: getBooleanValue, getStringValue, getNumberValue and getObjectValue each route through the matching A vs B typed getter, so the type the platform declared for a flag is checked at read time and a mismatch returns your default instead of the wrong shape. One rough edge remains: a type mismatch and a genuinely missing flag both resolve with errorCode: 'FLAG_NOT_FOUND', so read errorMessage when you need to tell them apart. There is no TYPE_MISMATCH code today; emitting one needs a machine-readable marker on Flag in @avsbhq/core.
Exposures still happen
Every resolution goes through the normal A vs B evaluation path, so it records an exposure for experiment rules exactly as a native read does. That is usually what you want on the server, where a read happens once per request for one visitor.
In the browser it deserves a second thought. OpenFeature reads are cheap and code tends to call them while rendering, and every one of those is an exposure. If you read a flag in a component that re-renders, prefer the native @avsbhq/browser client with { readOnly: true }, or one of the framework SDKs, whose render-path reads never fire exposures.
When to use the native SDK instead
Reach for @avsbhq/browser, @avsbhq/node, or a framework SDK when you want:
- Multi-context targeting: one evaluation against a user and an organization at once.
- Bandits and holdouts you can reason about, through
flag.sourceandflag.reasons. - Sticky bucketing backed by your own storage.
- Decision logs for auditing what a request decided.
- Exposure control: render-safe reads, and
manualExposurewhere the visitor actually sees the variation.
Everything above reaches an OpenFeature caller only as far as ResolutionDetails can carry it, which is the value, the variant, and a reason string.
Use OpenFeature when your codebase is already written against it, or when you are migrating vendor by vendor and want to swap the provider rather than the call sites.
Related
- OpenFeature integration: the working setup for the server and web SDKs.
- Multi-context identity: native SDKs only.
- SDK installation: the native quickstart.