Skip to main content

Introducing OpenFeature Support for Bucketeer Go SDK

· 5 min read
Naoki Kuroda
Software Engineer

Feature flags have become essential for modern software development, enabling teams to deploy code safely, test features with specific user segments, and roll out changes gradually. To address the challenge of vendor lock-in when switching between different feature flag providers, we're excited to announce OpenFeature support for the Bucketeer Go SDK.

This integration brings standardized feature flag evaluation to Bucketeer users while maintaining the high performance and reliability you've come to expect.

The Challenge and Our Solution

When teams choose a feature flag provider, they typically integrate deeply with that provider's specific APIs and data structures. This tight coupling creates several challenges:

  • Migration complexity: Switching providers requires significant code changes across the entire application
  • Testing difficulties: Different environments may need different providers, but code changes make this cumbersome
  • Vendor dependency: Teams become locked into specific providers, limiting their flexibility

To address these challenges, we've implemented OpenFeature support for Bucketeer's Go SDK. OpenFeature, a Cloud Native Computing Foundation (CNCF) project, provides a vendor-neutral, community-driven specification for feature flag evaluation that eliminates vendor lock-in while maintaining high performance and reliability.

Implementation Highlights

Unified API Experience

With OpenFeature support, you can now use the standardized API across different environments and providers:

// Create and set the provider
p, _ := provider.NewProviderWithContext(ctx, options)
openfeature.SetProvider(p)

// Create client and evaluate
client := openfeature.NewClient("my-app")
result, _ := client.BooleanValueDetails(ctx, "feature-flag", false, evalCtx)

This unified interface works consistently whether you're using Bucketeer, a test provider, or any other OpenFeature-compatible provider.

Automatic Context Conversion

Our implementation automatically handles the conversion between OpenFeature's EvaluationContext and Bucketeer's user model:

// OpenFeature evaluation context
userID := "user-123"
evalCtx := openfeature.NewEvaluationContext(userID, map[string]interface{}{
openfeature.TargetingKey: userID, // targeting key
"plan": "premium",
"region": "us-east",
"source": "web",
})

// Automatically converted to Bucketeer user format internally
result, _ := client.BooleanValueDetails(ctx, "premium-feature", false, evalCtx)

The conversion handles various data types intelligently:

  • String values are passed through directly
  • Complex objects are automatically serialized to JSON
  • The targetingKey is required and must be a string (used as Bucketeer's user ID)
  • Proper error handling ensures robust operation

Evaluation Reason Mapping

Bucketeer provides detailed evaluation reasons that help with debugging and understanding flag behavior. Our OpenFeature implementation maps these to standard OpenFeature reasons:

  • Target/Prerequisite/Rule evaluations → TargetingMatchReason
  • Default values → DefaultReason
  • OffVariation flags → DisabledReason
  • Error conditions (feature flag ID not specified, no evaluations, cache not found, exceptions) → ErrorReason
  • Other evaluations → Preserved as custom reasons

Getting Started

Installation

Add the OpenFeature provider to your Go project:

go get github.com/bucketeer-io/openfeature-go-server-sdk

Note
This is a beta version. Breaking changes may be introduced before general release.

Basic Setup

package main

import (
"context"
"log"

"github.com/bucketeer-io/go-server-sdk/pkg/bucketeer"
provider "github.com/bucketeer-io/openfeature-go-server-sdk/pkg"
"github.com/open-feature/go-sdk/openfeature"
)

func main() {
// SDK configuration options
options := provider.ProviderOptions{
bucketeer.WithAPIKey("YOUR_API_KEY"),
bucketeer.WithAPIEndpoint("YOUR_API_ENDPOINT"),
bucketeer.WithTag("YOUR_FEATURE_TAG"),
// Add other options as needed
}

// Create provider
p, err := provider.NewProviderWithContext(context.Background(), options)
if err != nil {
log.Fatal(err)
}

// Set the provider and create client
openfeature.SetProvider(p)
client := openfeature.NewClient("my-app")

// User configuration
userID := "targetingUserId"
evalCtx := openfeature.NewEvaluationContext(userID, map[string]interface{}{
openfeature.TargetingKey: userID,
// Add other attributes as needed
"plan": "premium",
"region": "us-west",
})

// Evaluate feature flags
showNewUIResult, err := client.BooleanValueDetails(context.Background(), "new-ui-enabled", false, evalCtx)
if err != nil {
log.Printf("Error evaluating new-ui-enabled: %v", err)
}

maxConnectionsResult, err := client.IntValueDetails(context.Background(), "max-connections", int64(100), evalCtx)
if err != nil {
log.Printf("Error evaluating max-connections: %v", err)
}

if showNewUIResult.Value {
log.Printf("Showing new UI for user with max %d connections", maxConnectionsResult.Value)
}
}

Flag Evaluation Types

The OpenFeature client supports evaluating different types of feature flags, each returning detailed evaluation results:

Boolean Evaluation

result, err := client.BooleanValueDetails(ctx, "feature-enabled", false, evalCtx)
if err != nil {
// Handle error
}
boolValue := result.Value
variant := result.Variant

String Evaluation

result, err := client.StringValueDetails(ctx, "theme-color", "blue", evalCtx)
if err != nil {
// Handle error
}
stringValue := result.Value

Integer Evaluation

result, err := client.IntValueDetails(ctx, "max-connections", int64(100), evalCtx)
if err != nil {
// Handle error
}
intValue := result.Value

Float Evaluation

result, err := client.FloatValueDetails(ctx, "retry-delay", 1.5, evalCtx)
if err != nil {
// Handle error
}
floatValue := result.Value

Object Evaluation

defaultConfig := map[string]interface{}{
"timeout": 30,
"retries": 3,
}
result, err := client.ObjectValueDetails(ctx, "service-config", defaultConfig, evalCtx)
if err != nil {
// Handle error
}
configValue := result.Value

Migration from Direct SDK Usage

If you're currently using the Bucketeer Go SDK directly, migration is straightforward:

// Before: Direct Bucketeer SDK usage
user := &user.User{
ID: "user-123",
Data: map[string]string{
"plan": "premium",
"region": "us-west",
},
}
result := sdk.BoolVariation(ctx, user, "feature-flag", false)

// After: OpenFeature with Bucketeer provider
userID := "user-123"
evalCtx := openfeature.NewEvaluationContext(userID, map[string]interface{}{
openfeature.TargetingKey: userID,
"plan": "premium",
"region": "us-west",
})
result, err := client.BooleanValueDetails(ctx, "feature-flag", false, evalCtx)
if err != nil {
// Handle error
}
value := result.Value

Platform Support and Future Plans

We've made significant progress across multiple platforms:

Currently Available:

  • Go: OpenFeature support (featured in this article)
  • Kotlin: Full OpenFeature compatibility for Android applications
  • Swift: Native OpenFeature support for iOS development
  • JavaScript: Browser-based OpenFeature integration

Coming Soon:

  • Node.js: Server-side JavaScript OpenFeature support
  • React Native: Cross-platform mobile OpenFeature integration

We're also actively working on:

  • Enhanced hooks: Supporting OpenFeature's hook system for custom evaluation logic
  • Community contributions: Contributing back to the OpenFeature ecosystem

Getting Started Today

The Bucketeer OpenFeature Go SDK is available now:

Whether you're starting a new project or considering migration from another provider, OpenFeature support makes Bucketeer an even more attractive choice for your feature flag management needs.

Conclusion

OpenFeature support for Bucketeer's Go SDK combines standardized APIs with high-performance feature flag management. Start using it today to avoid vendor lock-in while maintaining the reliability you expect.