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:

AdapterEntry pointWraps
AvsbProvider@avsbhq/utils/openfeatureAvsbServer from @avsbhq/node
AvsbWebProvider@avsbhq/utils/openfeatureAvsbClient 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:

LanguageProvider
PythonAvsbOpenFeatureProvider from avsb.openfeature_provider, installed with pip install "avsb[openfeature]"
GoNewProvider(server) from github.com/avsbhq/avsb-go/openfeature
.NETAvsbOpenFeatureProvider in Avsb.SDK, for OpenFeature .NET 2.0 or later
Javacom.avsbhq.avsb.OpenFeatureProvider
RubyAvsb::OpenFeatureProvider
PHPAvsbhq\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.

Warning

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:

  1. They do not import the OpenFeature packages. They are written against the shapes OpenFeature defines, so installing @avsbhq/utils never 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.
  2. 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

OpenFeatureA vs BNotes
targetingKeycontext.keyThe bucketing identifier.
Any other context propertyA targeting attributeAttached to a user kind context.
Multi-kind contextNot expressibleThe adapter always builds a single user context.
ResolutionDetails.valueFlag.value
ResolutionDetails.variantFlag.variationKeyundefined when the default was served.
ResolutionDetails.reasonFlag.source, upper-casedRULE, HOLDOUT, BANDIT, STICKY, DEFAULT, and so on. These are the A vs B sources upper-cased whole, not OpenFeature's standard reason strings.
flagMetadataruleId, ruleType, durationMicros
errorCodeSet for the two error sourcesA 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, statusNot 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.source and flag.reasons.
  • Sticky bucketing backed by your own storage.
  • Decision logs for auditing what a request decided.
  • Exposure control: render-safe reads, and manualExposure where 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.

Was this helpful?