Introducing OpenFeature Support for Bucketeer Go SDK
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:
- GitHub Repository: bucketeer-io/openfeature-go-server-sdk
- Complete Example: Check out the example directory for web application usage
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.