/Docs

OpenFeature Compatibility

A vs B ships first-party OpenFeature providers for every SDK. If your team uses OpenFeature as a vendor-neutral abstraction layer, you can plug in A vs B without changing how your application code evaluates flags.

What it is

OpenFeature is a CNCF specification and SDK that defines a common interface for feature flag evaluation. Applications code against the OF API; the underlying provider (LaunchDarkly, Flagsmith, A vs B, etc.) is swapped at configuration time. This makes it straightforward to migrate between vendors or run parallel evaluations during a migration.

The A vs B provider implements the full OF spec including typed resolution methods (resolveBooleanEvaluation, resolveStringEvaluation, resolveNumberEvaluation, resolveObjectEvaluation) and surfaces evaluation metadata via the OF ResolutionDetails shape.

When to use it

Use the OpenFeature provider when:

  • Your organisation already uses OpenFeature as a standard and other teams code against the OF API.
  • You are migrating from another vendor and want to switch the provider without touching application code.
  • You want a vendor-neutral abstraction that you can test with an in-memory provider in unit tests.

Use the native @avsbhq/browser or @avsbhq/node SDK directly when you need A vs B-specific features that go beyond the OF spec: multi-context kinded identity, bandit rules, decision log sinks, sticky bucketing configuration, or the Flag<T> envelope with reasons.

Info
The OF spec's EvaluationContext maps to A vs B's EvalContext 1:1. OpenFeature's targetingKey maps to our key field, and all other properties become targeting attributes on a user kind context by default. Multi-context and non-user kinds are available via the native SDK only.

How it works

The providers live in @avsbhq/utils/openfeature. Two classes are exported: AvsbProvider for the OF server SDK (@openfeature/server-sdk) and AvsbWebProvider for the OF web SDK (@openfeature/web-sdk). Both wrap the corresponding A vs B client and delegate evaluation to it.

The A vs B CI runs the official OpenFeature conformance test suite against both providers on every commit. Any conformance regression blocks the release.

Per-SDK usage

@avsbhq/browser (web)
ts
1import { OpenFeature } from '@openfeature/web-sdk'
2import { AvsbWebProvider } from '@avsbhq/utils/openfeature'
3import { AvsbClient } from '@avsbhq/browser'
4
5const avsbClient = new AvsbClient({ sdkKey: 'sdk_production_abc123' })
6await avsbClient.onReady()
7
8OpenFeature.setProvider(new AvsbWebProvider(avsbClient))
9
10// Standard OF evaluation — no A vs B-specific API
11const client = OpenFeature.getClient()
12const showBanner = client.getBooleanValue('show-promo-banner', false)
13const theme = client.getStringValue('homepage-theme', 'default')
@avsbhq/node (server)
ts
1import { OpenFeature } from '@openfeature/server-sdk'
2import { AvsbProvider } from '@avsbhq/utils/openfeature'
3import { AvsbServer } from '@avsbhq/node'
4
5const avsbServer = new AvsbServer({ sdkKey: process.env.AVSB_SDK_KEY })
6await avsbServer.onReady()
7
8OpenFeature.setProvider(new AvsbProvider(avsbServer))
9
10// Evaluate flags via the OF API — context passed per-call
11const client = OpenFeature.getClient()
12const flag = await client.getBooleanDetails('new-checkout', false, {
13 targetingKey: 'u_123',
14 plan: 'pro',
15})
16// flag.reason, flag.variant available in ResolutionDetails
avsb-python
python
1from openfeature import api
2from openfeature.evaluation_context import EvaluationContext
3from avsb import AvsbServer
4from avsb.openfeature import AvsbProvider
5
6server = AvsbServer(sdk_key=os.environ["AVSB_SDK_KEY"])
7server.wait_for_ready()
8
9api.set_provider(AvsbProvider(server))
10
11client = api.get_client()
12ctx = EvaluationContext(targeting_key="u_123", attributes={"plan": "pro"})
13
14show_banner = client.get_boolean_value("show-promo-banner", False, ctx)
avsb-java
java
1import dev.openfeature.sdk.OpenFeatureAPI;
2import dev.openfeature.sdk.MutableContext;
3import cloud.avsb.AvsbServer;
4import cloud.avsb.openfeature.AvsbProvider;
5
6AvsbServer server = AvsbServer.builder()
7 .sdkKey(System.getenv("AVSB_SDK_KEY"))
8 .build();
9server.blockUntilReady(Duration.ofSeconds(5));
10
11OpenFeatureAPI.getInstance().setProvider(new AvsbProvider(server));
12
13Client client = OpenFeatureAPI.getInstance().getClient();
14MutableContext ctx = new MutableContext("u_123");
15ctx.add("plan", "pro");
16
17boolean showBanner = client.getBooleanValue("show-promo-banner", false, ctx);
avsb-go
go
1import (
2 "github.com/open-feature/go-sdk/openfeature"
3 avsbOf "github.com/avsbhq/avsb-go/openfeature"
4 "github.com/avsbhq/avsb-go"
5)
6
7avsbClient, _ := avsb.NewServer(avsb.Options{SDKKey: os.Getenv("AVSB_SDK_KEY")})
8avsbClient.WaitForReady(context.Background())
9
10openfeature.SetProvider(avsbOf.NewProvider(avsbClient))
11
12client := openfeature.NewClient("my-app")
13ctx := openfeature.NewEvaluationContext("u_123", map[string]interface{}{"plan": "pro"})
14
15showBanner, _ := client.BooleanValue(context.Background(), "show-promo-banner", false, ctx)
avsb-dotnet
csharp
1using OpenFeature;
2using OpenFeature.Model;
3using Avsb;
4using Avsb.OpenFeature;
5
6var avsbServer = new AvsbServer(new AvsbOptions { SdkKey = Environment.GetEnvironmentVariable("AVSB_SDK_KEY") });
7await avsbServer.OnReadyAsync();
8
9Api.Instance.SetProvider(new AvsbProvider(avsbServer));
10
11var client = Api.Instance.GetClient();
12var ctx = EvaluationContext.Builder().SetTargetingKey("u_123").Set("plan", "pro").Build();
13
14bool showBanner = await client.GetBooleanValueAsync("show-promo-banner", false, ctx);