GO
The GO Feature Flag provider connects the OpenFeature Go SDK to a GO Feature Flag relay-proxy.
It supports two evaluation modes:
INPROCESSis the default. The provider fetches flag configuration from the relay-proxy, evaluates flags locally with the GO Feature Flag core library, and keeps the local configuration fresh by polling for updates.REMOTEdelegates every evaluation to the relay-proxy via OFREP: the relay-proxy remains the single source of truth, no local configuration or polling is needed, and flag changes take effect immediately on the server.
Install dependencies
Install the provider and the OpenFeature Go SDK:
go get github.com/open-feature/go-sdk-contrib/providers/go-feature-flag
Choose an evaluation mode
| Mode | Description | When to use it |
|---|---|---|
INPROCESS | Fetch configuration once, evaluate locally, poll for configuration changes. | Default choice for lower evaluation latency and the new 1.x.x behavior. |
REMOTE | A request is sent to the relay-proxy for each evaluation. | Single source of truth on the server, no local config or polling; flag changes apply immediately. |
Initialize your provider
INPROCESS is the default, so setting EvaluationType is optional, use REMOTE when you want to preserve the old remote-evaluation behavior while upgrading.
- In Process
- Remote
import (
"context"
gofeatureflag "github.com/open-feature/go-sdk-contrib/providers/go-feature-flag/pkg"
)
ctx := context.Background()
provider, err := gofeatureflag.NewProviderWithContext(ctx, gofeatureflag.ProviderOptions{
Endpoint: "http://localhost:1031",
EvaluationType: gofeatureflag.EvaluationTypeInProcess, // this line is optional because inprocess is the default
})
if err != nil {
// handle the error
}
import (
"context"
gofeatureflag "github.com/open-feature/go-sdk-contrib/providers/go-feature-flag/pkg"
)
ctx := context.Background()
provider, err := gofeatureflag.NewProviderWithContext(ctx, gofeatureflag.ProviderOptions{
Endpoint: "http://localhost:1031",
EvaluationType: gofeatureflag.EvaluationTypeRemote,
})
if err != nil {
// handle the error
}
Initialize your OpenFeature client
Register the provider in the OpenFeature SDK and then create a client:
import (
"context"
gofeatureflag "github.com/open-feature/go-sdk-contrib/providers/go-feature-flag/pkg"
of "github.com/open-feature/go-sdk/openfeature"
)
ctx := context.Background()
provider, err := gofeatureflag.NewProviderWithContext(ctx, gofeatureflag.ProviderOptions{
Endpoint: "http://localhost:1031",
})
if err != nil {
// handle the error
}
if err := of.SetProviderAndWait(provider); err != nil {
// handle the error
}
client := of.NewClient("my-app")
Evaluate a flag
Create an EvaluationContext and use the OpenFeature client as usual.
In this example we evaluate a boolean flag, but the provider also supports string, integer, float, and object evaluations.
See the OpenFeature evaluation API documentation for the full API surface.
evaluationCtx := of.NewEvaluationContext(
"1d1b9238-2591-4a47-94cf-d2bc080892f1",
map[string]any{
"firstname": "john",
"lastname": "doe",
"email": "john.doe@gofeatureflag.org",
"admin": true,
"anonymous": false,
},
)
adminFlag, err := client.BooleanValue(context.TODO(), "flag-only-for-admin", false, evaluationCtx)
if err != nil {
// handle the error
}
if adminFlag {
// flag "flag-only-for-admin" evaluated to true
} else {
// flag "flag-only-for-admin" evaluated to false
}
Provider options
Endpoint is required. The other options are optional.
| Option | Description |
|---|---|
Endpoint | Base URL of the GO Feature Flag relay-proxy (e.g. http://localhost:1031). Required. |
HTTPClient | Custom HTTP client. If omitted, the provider uses a default client with a 10-second timeout. |
APIKey | API key sent as X-API-Key. |
Headers | Extra headers added to provider HTTP requests. Useful for custom auth headers such as Authorization. |
ExporterMetadata | Metadata attached to exported evaluation and tracking events. |
EvaluationType | Selects INPROCESS or REMOTE. Default is INPROCESS. |
FlagChangePollingInterval | Poll interval used in INPROCESS mode to refresh the local flag configuration. |
DataCollectorMaxEventStored | Maximum number of buffered events before the collector flushes the queue on a subsequent add. |
DataCollectorCollectInterval | Interval used to send buffered events to the relay-proxy data collector. |
DataCollectorDisabled | Disables event collection and tracking export. |
DataCollectorBaseURL | Overrides the base URL used only for the data collector endpoint. |
Logger | Custom slog.Logger used by the provider. |
Tracking and event collection
Flag usage events (automatic)
In INPROCESS mode, the provider automatically collects a flag evaluation event every time a flag is evaluated. These events are batched in memory and flushed to the relay-proxy data collector endpoint (POST /v1/data/collector) periodically or when the buffer is full.
Each event records:
- The flag key and the variation that was served
- The user key and whether the user was anonymous
- The resolved value and whether the SDK default was returned
- A creation timestamp
The flush is also triggered on provider shutdown so no buffered events are lost.
Custom tracking events (OpenFeature Track API)
The provider implements the OpenFeature Tracker interface. Call client.Track() to send a named tracking event with arbitrary attributes:
client.Track(
context.TODO(),
"user-checkout",
of.NewEvaluationContext(
"1d1b9238-2591-4a47-94cf-d2bc080892f1",
map[string]any{
"plan": "premium",
},
),
of.NewTrackingEventDetails(99.99),
)
Tracking events are queued in the same data collector buffer as flag evaluation events and sent to the same relay-proxy endpoint.
Disabling and tuning event collection
Use the DataCollector* options to tune or disable collection:
| Option | Default | Description |
|---|---|---|
DataCollectorDisabled | false | Set to true to disable all event collection. |
DataCollectorCollectInterval | 2 minutes | How often buffered events are flushed to the relay-proxy. |
DataCollectorMaxEventStored | 100 000 | Buffer size. When the buffer is full the provider flushes immediately before queuing the next event. |
DataCollectorBaseURL | same as Endpoint | Override the base URL used only for the data collector endpoint. |
Operational notes
- In
INPROCESSmode, the provider fetches configuration from/v1/flag/configuration, evaluates locally, and emits provider events such asProviderConfigChange,ProviderStale, andProviderReady. - In
REMOTEmode, evaluations go through OFREP instead of the local evaluator. - The local data-collector hook is attached only in
INPROCESSmode.Trackstill uses the provider data collector when collection is enabled. - If your relay-proxy expects bearer-token auth instead of
X-API-Key, set it explicitly withHeaders, for exampleHeaders: map[string]string{"Authorization": "Bearer <token>"}.
Migrating from v0.x.x to v1.x.x
INPROCESS mode is the recommended target for all users. It eliminates a network round-trip per evaluation, reduces load on the relay-proxy, and enables automatic flag usage tracking. The migration below gets you there directly.
- Upgrade the dependency to the new provider version.
- Rename or remove old options that no longer exist.
- Remove any explicit
EvaluationTypesetting —INPROCESSis the default. - Tune
FlagChangePollingIntervaland data-collector settings for your production traffic profile.
If you need a temporary stepping stone while validating the upgrade, you can pin REMOTE mode to keep the old evaluation behavior:
options := gofeatureflag.ProviderOptions{
Endpoint: "http://localhost:1031",
EvaluationType: gofeatureflag.EvaluationTypeRemote,
}
Option mapping from 0.x.x to 1.x.x:
0.x.x option | 1.x.x status |
|---|---|
DisableCache | Removed. 1.x.x no longer uses the old provider-managed evaluation cache model. |
FlagCacheSize | Removed. |
FlagCacheTTL | Removed. |
DataFlushInterval | Renamed to DataCollectorCollectInterval. |
DisableDataCollector | Renamed to DataCollectorDisabled. |
Authentication migration note:
- In
0.x.x, the provider's remote evaluation path used bearer-token auth forAPIKey. - In
1.x.x,APIKeyis sent asX-API-Key. - If you still need
Authorization: Bearer ..., useHeadersinstead ofAPIKey.
Difference between 0.x.x and 1.x.x
| Topic | 0.x.x | 1.x.x |
|---|---|---|
| Default behavior | Remote evaluation through the relay-proxy. | In-process evaluation is the default. |
| Evaluation model | Each evaluation goes through the remote path, optionally backed by the provider cache. | Configuration is fetched from the relay-proxy and evaluations happen locally. |
| Cache behavior | Provider-managed cache controlled by DisableCache, FlagCacheSize, and FlagCacheTTL. | No equivalent cache layer in the provider API. Freshness comes from configuration polling. |
| Polling purpose | Polling was used to invalidate cached flag data. | Polling refreshes the in-process configuration used for local evaluations. |
| Compatibility mode | Not applicable. | EvaluationTypeRemote preserves the old remote pattern while migrating. |
| Auth behavior | APIKey on the remote path was bearer-token based. | APIKey uses X-API-Key; custom auth can be passed with Headers. |
| Data collector config | DataFlushInterval and DisableDataCollector. | DataCollectorCollectInterval, DataCollectorDisabled, and DataCollectorBaseURL. |
Features status
| Status | Feature | Description |
|---|---|---|
| In process Evaluation | The provider is able to evaluate the feature flags in process, it loads the configuration from the relay-proxy and perform evaluation inside the SDK. | |
| Remote Evaluation | The provider is calling the remote server to evaluate the feature flags. | |
| Tracking Flag Evaluation | The provider is tracking all the evaluations of your feature flags and you can export them using an exporter. | |
| Tracking Custom Events | The provider is tracking custom events through the track() function of your SDK. All those events are send to the exporter for you to forward them where you want. | |
| Configuration Change Updates | The provider is able to update the configuration based on the configuration, it means that the provider is able to react to any feature flag change on your configuration. | |
| Provider Events Reactions | You can add an event handler to the provider to react to the provider events. |
Contribute to the provider
You can find the source of the provider in the open-feature/go-sdk-contrib repository.