OpenFeature Providers
OpenFeature is a CNCF-incubating open standard for feature flagging. GrowthBook provides OpenFeature provider SDKs for Python, Go, .NET, and Java — listed in the OpenFeature ecosystem.
Prerequisites
- A GrowthBook account (cloud or self-hosted)
- An SDK Connection key — create one under Settings → SDK Connections in the GrowthBook UI
- The API host:
- Cloud:
https://cdn.growthbook.io - Self-hosted: your own GrowthBook URL (e.g.
https://growthbook.example.com)
- Cloud:
Why Use OpenFeature with GrowthBook?
OpenFeature defines a vendor-neutral interface for evaluating feature flags. Using a GrowthBook OpenFeature provider means:
- Vendor portability — Your flag evaluation code is identical regardless of which provider is active. Switching from or to GrowthBook only requires changing the provider bootstrap, not a single flag call.
- Standardized API — Teams use the same OpenFeature interface they already know across all services.
- Ecosystem compatibility — OpenFeature-aware tooling — including OpenTelemetry hooks and other instrumentation — works automatically with GrowthBook.
- Polyglot consistency — The same conceptual API spans Python, Go, .NET, Java (and more), giving teams a single mental model.
The native GrowthBook SDKs expose features that go beyond the OpenFeature interface: Sticky Bucketing, Visual Editor experiments, inline experiment definitions, and real-time SSE streaming. If you need those capabilities, use the native SDK for your language instead.
Installation & Setup
- Python
- Go
- .NET
- Java
GitHub: growthbook-openfeature-provider-python | PyPI: growthbook-openfeature-provider
Requirements: Python 3.9+
pip install growthbook-openfeature-provider
Async setup (recommended for async frameworks like FastAPI, aiohttp):
import asyncio
from openfeature.api import OpenFeatureAPI
from openfeature.evaluation_context import EvaluationContext
from growthbook_openfeature_provider import GrowthBookProvider, GrowthBookProviderOptions
async def main():
provider = GrowthBookProvider(GrowthBookProviderOptions(
api_host="https://cdn.growthbook.io",
client_key="sdk-abc123"
))
await provider.initialize()
OpenFeatureAPI.set_provider(provider)
client = OpenFeatureAPI.get_client("my-app")
# ... evaluate flags ...
await provider.close()
asyncio.run(main())
Synchronous setup:
from openfeature.api import OpenFeatureAPI
from growthbook_openfeature_provider import GrowthBookProvider, GrowthBookProviderOptions
provider = GrowthBookProvider(GrowthBookProviderOptions(
api_host="https://cdn.growthbook.io",
client_key="sdk-abc123"
))
provider.initialize_sync()
OpenFeatureAPI.set_provider(provider)
client = OpenFeatureAPI.get_client("my-app")
GitHub: growthbook-openfeature-provider-go | pkg.go.dev: growthbook-openfeature-provider-go
Requirements: Go 1.21+
go get github.com/growthbook/growthbook-openfeature-provider-go
import (
"context"
"log"
gb "github.com/growthbook/growthbook-golang"
gbprovider "github.com/growthbook/growthbook-openfeature-provider-go"
"github.com/open-feature/go-sdk/openfeature"
)
// Create the underlying GrowthBook client
gbClient, err := gb.NewClient(context.Background(),
gb.WithAPIHost("https://cdn.growthbook.io"),
gb.WithClientKey("sdk-abc123"),
)
if err != nil {
log.Fatal("GrowthBook client initialization failed: ", err)
}
defer gbClient.Close()
// Wrap it in the OpenFeature provider and register it
provider := gbprovider.NewProvider(gbClient)
if err = openfeature.SetProvider(provider); err != nil {
log.Fatal("Failed to set OpenFeature provider: ", err)
}
client := openfeature.NewClient("my-app")
GitHub: growthbook-openfeature-provider-dot-net | NuGet: GrowthBook.OpenFeature
Requirements: .NET 8+ or .NET Framework 4.6.2+
dotnet add package GrowthBook.OpenFeature
using GrowthBook.OpenFeature;
using OpenFeature;
using OpenFeature.Model;
var provider = new GrowthBookProvider(
clientKey: "sdk-abc123",
apiHostUrl: "https://cdn.growthbook.io"
);
Api.Instance.SetProvider(provider);
var client = Api.Instance.GetClient();
GitHub: growthbook-openfeature-provider-java | Maven Central: growthbook-openfeature-provider-java
Requirements: Java 8+
- Maven
- Gradle
<dependency>
<groupId>com.github.growthbook</groupId>
<artifactId>growthbook-openfeature-provider-java</artifactId>
<version>0.0.1</version>
</dependency>
implementation group: 'com.github.growthbook', name: 'growthbook-openfeature-provider-java', version: '0.0.1'
import io.github.growthbook.GrowthBookProvider;
import io.github.growthbook.Options;
import dev.openfeature.sdk.OpenFeatureAPI;
import dev.openfeature.sdk.Client;
Options options = Options.builder()
.apiHost("https://cdn.growthbook.io")
.clientKey("sdk-abc123")
.build();
GrowthBookProvider provider = new GrowthBookProvider(options);
OpenFeatureAPI.getInstance().setProvider(provider);
Client client = OpenFeatureAPI.getInstance().getClient();
Evaluation Context (Targeting Attributes)
Pass user attributes to the OpenFeature client via an EvaluationContext. These become GrowthBook targeting attributes used for percentage rollouts, feature targeting rules, and experiment bucketing.
The targetingKey maps to the user ID in GrowthBook. Additional attributes (e.g. country, plan, email) are matched against your feature flag targeting conditions.
- Python
- Go
- .NET
- Java
from openfeature.evaluation_context import EvaluationContext
context = EvaluationContext(
targeting_key="user-123",
attributes={
"country": "US",
"plan": "premium",
"email": "user@example.com",
}
)
evalCtx := openfeature.NewEvaluationContext("user-123", map[string]interface{}{
"country": "US",
"plan": "premium",
"email": "user@example.com",
})
var context = new EvaluationContext(
targetingKey: "user-123",
new Dictionary<string, Value>
{
{ "country", new Value("US") },
{ "plan", new Value("premium") },
{ "email", new Value("user@example.com") },
}
);
import dev.openfeature.sdk.EvaluationContext;
import dev.openfeature.sdk.MutableContext;
MutableContext context = new MutableContext("user-123");
context.add("country", "US");
context.add("plan", "premium");
context.add("email", "user@example.com");
Evaluating Feature Flags
OpenFeature defines five value types. GrowthBook's feature flags map to all of them.
Boolean
The most common type — use for on/off feature gates.
- Python
- Go
- .NET
- Java
# Synchronous
enabled = client.get_boolean_value("dark-mode", False, context)
# Async (returns FlagEvaluationDetails with value, reason, variant, etc.)
details = await provider.resolve_boolean_details_async("dark-mode", False, context)
enabled = details.value
// Returns the value with a default fallback
enabled, err := client.BooleanValue(context.Background(), "dark-mode", false, evalCtx)
// Returns full evaluation details (value, reason, variant, error)
details, err := client.BooleanValueDetails(context.Background(), "dark-mode", false, evalCtx)
enabled := details.Value
bool enabled = await client.GetBooleanValue("dark-mode", false, context);
boolean enabled = client.getBooleanValue("dark-mode", false, context);
String
Use for multi-variant flags where the value is a string (e.g. button color, layout variant).
- Python
- Go
- .NET
- Java
variant = client.get_string_value("button-color", "blue", context)
variant, err := client.StringValue(context.Background(), "button-color", "blue", evalCtx)
string variant = await client.GetStringValue("button-color", "blue", context);
String variant = client.getStringValue("button-color", "blue", context);
Integer & Float/Double
Use for numeric feature values such as rate limits, timeouts, or pricing.
- Python
- Go
- .NET
- Java
request_limit = client.get_integer_value("api-request-limit", 100, context)
price = client.get_float_value("subscription-price", 9.99, context)
requestLimit, err := client.IntValue(context.Background(), "api-request-limit", 100, evalCtx)
price, err := client.FloatValue(context.Background(), "subscription-price", 9.99, evalCtx)
int requestLimit = await client.GetIntegerValue("api-request-limit", 100, context);
double price = await client.GetDoubleValue("subscription-price", 9.99, context);
int requestLimit = client.getIntegerValue("api-request-limit", 100, context);
double price = client.getDoubleValue("subscription-price", 9.99, context);
Object
Use for structured feature values (e.g. configuration payloads, theme objects).
- Python
- Go
- .NET
- Java
config = client.get_object_value("theme-config", {"color": "blue"}, context)
// Object values are returned as map[string]interface{}
config, err := client.ObjectValue(context.Background(), "theme-config", map[string]interface{}{}, evalCtx)
Value config = await client.GetObjectValue("theme-config",
new Value(new Dictionary<string, Value>()), context);
Value config = client.getObjectValue("theme-config", new MutableStructure(), context);
Configuration Options
| Option | Python | Go | .NET | Java | Description |
|---|---|---|---|---|---|
api_host / apiHost | ✓ | ✓ | ✓ | ✓ | GrowthBook CDN or self-hosted URL |
client_key / clientKey | ✓ | ✓ | ✓ | ✓ | SDK Connection key from GrowthBook |
decryption_key | ✓ | — | — | — | Key for encrypted SDK endpoint payloads |
cache_ttl | ✓ | ✓ | — | — | Seconds before re-fetching features (default: 60) |
enabled | ✓ | — | ✓ | — | Enable/disable the provider entirely |
qa_mode | ✓ | — | — | — | Forces all experiments into the control variation |
Shutdown & Cleanup
Always shut down the provider when your application exits to close background connections.
- Python
- Go
- .NET
- Java
await provider.close() # async
# or
provider.close_sync() # sync
defer gbClient.Close()
provider.Dispose();
provider.shutdown();
Further Reading
- OpenFeature specification — the full standard
- GrowthBook on the OpenFeature ecosystem
- Native GrowthBook SDKs — for Sticky Bucketing, Visual Editor, SSE streaming, and more