Skip to content

Go Feature Flags Quickstart

This guide gets you from zero to evaluating a feature flag in a Go application. The SDK requires Go 1.25+.

  • A Featureflip account with at least one feature flag created
  • An SDK key from your environment settings
  • Go 1.25+
Terminal window
go get github.com/canopy-labs/featureflip-go
package main
import (
"fmt"
"log"
featureflip "github.com/canopy-labs/featureflip-go"
)
func main() {
client, err := featureflip.Get("your-sdk-key",
featureflip.WithBaseURL("https://eval.featureflip.io"),
)
if err != nil {
log.Fatalf("Failed to initialize: %v", err)
}
defer client.Close()
}

Get blocks until the initial flag configuration is fetched. It returns an error if the fetch fails or times out (10 seconds by default).

If you prefer, set the FEATUREFLIP_SDK_KEY environment variable and pass an empty string:

client, err := featureflip.Get("")
ctx := featureflip.EvaluationContext{UserID: "user-123"}
showBanner := client.BoolVariation("new-banner", ctx, false)
if showBanner {
fmt.Println("Showing the new banner")
} else {
fmt.Println("Using the default experience")
}

The third argument is the default value returned when the flag is not found or evaluation fails.

Other variation methods are available for different value types:

color := client.StringVariation("banner-color", ctx, "blue")
limit := client.Float64Variation("rate-limit", ctx, 100.0)
config := client.JSONVariation("ui-config", ctx, map[string]any{})

You can attach custom attributes to the evaluation context for use in targeting rules:

ctx := featureflip.EvaluationContext{
UserID: "user-123",
Attributes: map[string]any{
"plan": "pro",
"country": "US",
},
}

Use defer client.Close() immediately after creating the client, as shown in the initialization example. This flushes pending analytics events and stops background goroutines when your application exits.

The Go SDK evaluates flags locally in your process — no per-request network calls. Get blocks on startup while it fetches the initial flag configuration over HTTPS. Once initialized, the client spawns a background goroutine that maintains an SSE streaming connection to the evaluation API, applying configuration updates as they arrive. If streaming is unavailable, it falls back to polling every 30 seconds.

All variation methods (BoolVariation, StringVariation, etc.) read from an in-memory store protected by a sync.RWMutex, so they are safe to call concurrently from any goroutine without external synchronization. Always pair Get with defer client.Close() — this stops the background goroutine, flushes pending analytics events, and releases the HTTP connection. Without it, the goroutine and its SSE connection leak until the process exits.

If the streaming connection drops, the SDK continues serving the last known configuration. Flag evaluations remain instantaneous throughout — the only thing that pauses is receiving updates.

Get returns an error immediately

The most common cause is an invalid SDK key or an unreachable evaluation API. Verify the key matches your target environment and that your application can reach eval.featureflip.io over HTTPS. If you use a custom WithBaseURL, make sure it includes the protocol.

Flags return default values even though the dashboard shows them enabled

Flag keys are case-sensitive. Double-check the key string matches the dashboard exactly. Also confirm the flag is enabled in the specific environment that corresponds to your SDK key — a flag enabled in “Production” is not automatically enabled in “Development.”

Import path errors after go get

The module path is github.com/canopy-labs/featureflip-go. Ensure your import matches this exactly. If you see version resolution errors, try running go mod tidy to clean up your go.mod and go.sum files.