Skip to content

setbit-io/setbit-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SetBit Go SDK

Official Go SDK for SetBit - Simple feature flags and A/B testing.

Features

  • βœ… Boolean Flags - Simple on/off feature toggles
  • πŸ§ͺ A/B Testing - Weighted variant distribution for experiments
  • πŸ“Š Conversion Tracking - Track events and conversions
  • 🏷️ Tag-Based Targeting - Target by environment, app, team, region, etc.
  • πŸš€ Fail-Open Design - Returns defaults if API is unreachable
  • πŸͺΆ Lightweight - Zero dependencies (uses only Go standard library)
  • ⚑ Fast - Built-in HTTP connection pooling and timeouts

Installation

go get github.com/setbit-io/setbit-go

Quick Start

package main

import (
    "log"

    "github.com/setbit-io/setbit-go"
)

func main() {
    // Initialize the client
    client, err := setbit.NewClient(setbit.Config{
        APIKey: "pk_your_api_key_here",
        Tags: map[string]string{
            "env": "production",
            "app": "web",
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    // Check a boolean flag (user ID required for analytics)
    userID := getCurrentUserID()
    if client.Enabled("new-checkout", userID, false) {
        showNewCheckout()
    } else {
        showOldCheckout()
    }

    // Get A/B test variant
    variant := client.Variant("pricing-experiment", userID, "control")
    switch variant {
    case "variant_a":
        showPrice99()
    case "variant_b":
        showPrice149()
    default:
        showPrice129()
    }

    // Track conversions (pass variant for proper attribution)
    client.Track("purchase", userID, setbit.TrackOptions{
        FlagName: "pricing-experiment",
        Variant:  variant,
        Metadata: map[string]interface{}{
            "amount": 99.99,
        },
    })
}

API Reference

Initialization

client, err := setbit.NewClient(setbit.Config{
    APIKey: "pk_your_api_key",
    Tags: map[string]string{
        "env": "production",
        "app": "web",
        "region": "us-east",
    },
    BaseURL: "https://flags.setbit.io", // Optional, custom endpoint
    HTTPClient: &http.Client{},         // Optional, custom HTTP client
    Logger: log.New(os.Stdout, "setbit: ", 0), // Optional, custom logger
})

Config Parameters:

  • APIKey (string, required): Your SetBit API key
  • Tags (map[string]string, optional): Tags for targeting flags
  • BaseURL (string, optional): API endpoint URL (useful for self-hosted instances)
  • HTTPClient (*http.Client, optional): Custom HTTP client
  • Logger (*log.Logger, optional): Custom logger (silent by default)

Returns:

  • *Client: SetBit client instance
  • error: Error if configuration is invalid (e.g., missing API key)

Enabled(flagName, userID string, defaultValue bool) bool

Check if a flag is enabled. Returns true if the flag is globally enabled, false otherwise.

Parameters:

  • flagName (string): Name of the flag
  • userID (string, required): User identifier (required for analytics and billing)
  • defaultValue (bool): Value to return if flag not found (default behavior on error)

Returns: bool - true if enabled, false otherwise

Note: This method returns whether the flag is globally enabled. For rollout flags, use Variant() to check which rollout group the user is in.

Example:

// Check if flag is enabled
if client.Enabled("new-feature", userID, false) {
    // Show new feature
}

// With default true (fail open)
if client.Enabled("beta-access", userID, true) {
    // Grant beta access
}

Variant(flagName, userID, defaultVariant string) string

Get the variant for an A/B test experiment or percentage rollout.

Parameters:

  • flagName (string): Name of the experiment flag
  • userID (string, required): User identifier
  • defaultVariant (string): Default variant if flag not found (e.g., "control")

Returns: string - Variant name (e.g., "control", "variant_a", "variant_b")

Note: Returns the defaultVariant if the flag is disabled or API is unreachable.

Example:

// A/B test
variant := client.Variant("pricing-experiment", userID, "control")
switch variant {
case "variant_a":
    // Show variant A
case "variant_b":
    // Show variant B
default:
    // Show control
}

// Percentage rollout
variant := client.Variant("new-api-rollout", userID, "control")
if variant == "enabled" {
    useNewAPI()
} else {
    useOldAPI()
}

Track(eventName, userID string, opts TrackOptions)

Track a conversion event or user action.

Parameters:

  • eventName (string): Name of the event (e.g., "purchase", "signup", "click")
  • userID (string, required): User identifier
  • opts (TrackOptions): Optional tracking options
    • FlagName (string): Flag name to associate with event
    • Variant (string): Variant the user was assigned to (for A/B test attribution)
    • Metadata (map[string]interface{}): Additional metadata

Returns: Nothing (fails silently, logs errors)

Example:

// Track conversion with variant attribution (recommended for A/B tests)
variant := client.Variant("pricing-experiment", userID, "control")
// ... later when user converts ...
client.Track("purchase", userID, setbit.TrackOptions{
    FlagName: "pricing-experiment",
    Variant:  variant,
    Metadata: map[string]interface{}{
        "amount": 99.99,
        "currency": "USD",
    },
})

// Track without flag association
client.Track("signup", userID, setbit.TrackOptions{
    Metadata: map[string]interface{}{
        "source": "organic",
    },
})

// Track simple event
client.Track("button_click", userID, setbit.TrackOptions{})

Advanced Usage

Custom HTTP Client

customClient := &http.Client{
    Timeout: 10 * time.Second,
    Transport: &http.Transport{
        MaxIdleConns: 100,
    },
}

client, _ := setbit.NewClient(setbit.Config{
    APIKey: "pk_your_api_key",
    HTTPClient: customClient,
})

Custom Logger

logger := log.New(os.Stdout, "setbit: ", log.LstdFlags)

client, _ := setbit.NewClient(setbit.Config{
    APIKey: "pk_your_api_key",
    Logger: logger,
})

Self-Hosted Instance

client, _ := setbit.NewClient(setbit.Config{
    APIKey: "pk_your_api_key",
    BaseURL: "https://flags.yourcompany.com",
})

Error Handling

The SDK is designed to fail open - if the API is unreachable or returns an error, methods return the specified default values rather than blocking your application.

// If API fails, returns false (safe default)
enabled := client.Enabled("risky-feature", userID, false)

// If API fails, returns "control" (safe default)
variant := client.Variant("experiment", userID, "control")

// Track fails silently (logs error but doesn't block)
client.Track("event", userID, setbit.TrackOptions{})

Best Practices

1. User ID is Required

Always provide a user ID for all flag evaluations. This is required for:

  • Analytics and reporting
  • Billing (MAU tracking)
  • Consistent variant assignment in A/B tests
// βœ… Good - user ID provided
if client.Enabled("feature", userID, false) {
    // ...
}

// ❌ Bad - empty user ID
if client.Enabled("feature", "", false) {
    // This will still work but won't be tracked properly
}

2. Choose Appropriate Defaults

// For new features, default to false (conservative)
if client.Enabled("experimental-feature", userID, false) {
    // Only enable if API confirms
}

// For stable features, default to true (progressive)
if client.Enabled("stable-feature", userID, true) {
    // Enable even if API is down
}

3. Cache the Client Instance

Create one client instance and reuse it throughout your application:

// Initialize once
var flagClient *setbit.Client

func init() {
    var err error
    flagClient, err = setbit.NewClient(setbit.Config{
        APIKey: os.Getenv("SETBIT_API_KEY"),
        Tags: map[string]string{
            "env": os.Getenv("ENV"),
        },
    })
    if err != nil {
        log.Fatal(err)
    }
}

// Reuse everywhere
func handler(w http.ResponseWriter, r *http.Request) {
    if flagClient.Enabled("feature", getUserID(r), false) {
        // ...
    }
}

4. Use Tags for Organization

client, _ := setbit.NewClient(setbit.Config{
    APIKey: "pk_your_api_key",
    Tags: map[string]string{
        "env": "production",     // Environment
        "app": "api",           // Application/service name
        "team": "backend",      // Team ownership
        "region": "us-east-1",  // Geographic region
    },
})

Testing

Run the test suite:

go test -v

Run tests with coverage:

go test -v -cover

Examples

See example.go for a complete working example.

Run the example:

go run example.go

Requirements

  • Go 1.21 or higher
  • No external dependencies (uses only Go standard library)

License

MIT License - see LICENSE file for details

Support

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

About

Go SDK for SetBit feature flagging

Resources

License

Stars

Watchers

Forks

Packages

No packages published