8000 GitHub - thomaspoignant/go-feature-flag: GO Feature Flag is a simple, complete and lightweight self-hosted feature flag solution 100% Open Source. ๐ŸŽ›๏ธ
[go: up one dir, main page]

Skip to content

GO Feature Flag is a simple, complete and lightweight self-hosted feature flag solution 100% Open Source. ๐ŸŽ›๏ธ

License

Notifications You must be signed in to change notification settings
  • Insights
  • thomaspoignant/go-feature-flag

    Folders and files

    NameName
    Last commit message
    Last commit date

    Latest commit

    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 
    ย 

    go-feature-flag logo

    ๐ŸŽ›๏ธ GO Feature Flag

    Build Status Sonarcloud Status Release version Build Status License
    GoDoc Go version Mentioned in Awesome Go Join us on slack Sponsords
    GO Feature Flag is a simple, complete and lightweight self-hosted feature flag solution 100% Open Source.

    ๐Ÿ™ If you are using GO Feature Flag please consider to add yourself in the adopters list.
    This simple act significantly boosts the project's visibility and credibility, making a substantial contribution to its advancement.

    If you want to support me and GO Feature Flag, you can also become a sponsor.

    Table of Contents

    What is GO Feature Flag?

    GO Feature Flag is a lightweight and open-source solution that provides a simple and complete feature flag implementation.

    The solution has been built to facilitate the usage of feature flags in your code with the easiest setup possible.

    Originally, GO Feature Flag was designed as a solution exclusively for the GO language. With the new standardization of feature flags by the Openfeature project, the solution is now available for multiple languages (list of supported languages) through a simple API server called the relay proxy, which can be hosted.

    Tip

    If you are not familiar with feature flags, I've written an article which explains why feature flags can fasten your iteration cycle.

    What can I do with GO Feature Flag?

    • Use the feature flag standard OpenFeature in your favorite language (see list).
    • Storing your configuration flags file on various locations (HTTP, S3, Kubernetes, see full list).
    • Configuring your flags in various format (JSON, TOML and YAML).
    • Adding complex rules to target your users.
    • Use a complex rollout strategy for your flags :
    • Exporting your flags usage data to various destinations such as (S3, Google cloud storage, file, kubernetes, see the full list).
    • Getting notified when a flag has been changed (webhook and slack).
    • Support your full stack, from the backend to the frontend including your mobile apps.
    Screen.Recording.2025-08-01.at.10.05.37.mov

    The code of this demo is available in examples/demo repository.

    Part of the OpenFeature Ecosystem

    At GO Feature Flag, we believe in the power of open standards and, the importance of vendor neutrality. That's why we've chosen to rely on Open Feature for our SDKs.

    By adopting GO Feature Flag you embrace the OpenFeature standard and you get all the benefits of the ecosystem.

    • Open-Source standard SDKs
    • No Vendor Lock-In
    • OpenFeature community based support for SDKs

    Getting started

    Important

    Before starting to use GO Feature Flag you should decide if you want to use Open Feature SDKs or if you want to use GO Feature Flag as a GO Module.

    We recommend using the relay-proxy for a central flag management and evaluation solution, it enables the multi-languages support, and it integrates seamlessly with the Open Feature SDKs.
    This is the best way to get full potential of GO Feature Flag.

    If your project is exclusively in GO, the GO module is an option. It will perform the flag evaluation directly in your GO code.

    Using Open Feature SDKs

    Create a feature flag configuration

    Create a new YAML file containing your first flag configuration.

    # 20% of the users will use the variation "my-new-feature"
    test-flag:
      variations:
        my-new-feature: true
        my-old-feature: false
      defaultRule:
        percentage:
          my-new-feature: 20
          my-old-feature: 80

    This flag split the usage of this flag, 20% will use the variation my-new-feature and 80% the variation my-old-feature.

    Create a relay proxy configuration file

    Create a new YAML file containing the configuration of your relay proxy.

    server:
      mode: http
      port: 1031
    pollingInterval: 1000
    startWithRetrieverError: false
    retriever:
      kind: file
      path: /goff/flag-config.yaml
    exporter:
      kind: log

    Install the relay proxy

    And we will run the relay proxy locally to make the API available.
    The default port will be 1031.

    # Launch the container
    docker run \
      -p 1031:1031 \
      -v $(pwd)/flag-config.yaml:/goff/flag-config.yaml \
      -v $(pwd)/goff-proxy.yaml:/goff/goff-proxy.yaml \
      gofeatureflag/go-feature-flag:latest
    

    If you don't want to use docker to install the relay proxy you can follow other ways to install it in the documentation.

    Use Open Feature SDK

    In this example, we are using the nodejs SDK, but you can check other languages here.

    Install dependencies

    npm i @openfeature/server-sdk @openfeature/go-feature-flag-provider

    Init your Open Feature client

    In your app initialization, you have to create a client using the Open Feature SDK and initialize it.

    const {OpenFeature} = require("@openfeature/server-sdk");
    const {GoFeatureFlagProvider} = require("@openfeature/go-feature-flag-provider");
    
    
    // init Open Feature SDK with GO Feature Flag provider
    const goFeatureFlagProvider = new GoFeatureFlagProvider({
      endpoint: 'http://localhost:1031/' // DNS of your instance of relay proxy
    });
    OpenFeature.setProvider(goFeatureFlagProvider);
    const featureFlagClient = OpenFeature.getClient('my-app')

    Evaluate your flag

    Now you can evaluate your flags anywhere in your code using this client.

    // Context of your flag evaluation.
    // With GO Feature Flag you MUST provide a targetingKey that is a unique identifier of the user.
    const evaluationContext = {
      targetingKey: '1d1b9238-2591-4a47-94cf-d2bc080892f1', // user unique identifier (mandatory)
      firstname: 'john',
      lastname: 'doe',
      email: 'john.doe@gofeatureflag.org',
      admin: true, // this field is used in the targeting rule of the flag "flag-only-for-admin"
      // ...
    };
    
    const adminFlag = await featureFlagClient.getBooleanValue('flag-only-for-admin', false, evaluationContext);
    if (adminFlag) {
      // flag "flag-only-for-admin" is true for the user
      console.log("new feature");
    } else {
      // flag "flag-only-for-admin" is false for the user
    }

    Using the GO Module

    Installation

    go get github.com/thomaspoignant/go-feature-flag

    Create a feature flag configuration

    Create a new YAML file containing your first flag configuration.

    # 20% of the users will use the variation "my-new-feature"
    test-flag:
      variations:
        my-new-feature: true
        my-old-feature: false
      defaultRule:
        percentage:
          my-new-feature: 20
          my-old-feature: 80

    This flag split the usage of this flag, 20% will use the variation my-new-feature and 80% the variation my-old-feature.

    SDK Initialisation

    First, you need to initialize the ffclient with the location of your backend file.

    err := ffclient.Init(ffclient.Config{
      PollingInterval: 3 * time.Second,
      Retriever:      &fileretriever.Retriever{
        Path: "flag-config.goff.yaml",
      },
    })
    defer ffclient.Close()

    This example will load a file from your local computer and will refresh the flags every 3 seconds (if you omit the PollingInterval, the default value is 60 seconds).

    โ„น info
    This is a basic configuration to test locally, in production it is better to use a remote place to store your feature flag configuration file.
    Look at the list of available options in the Store your feature flag file page.

    Evaluate your flags

    Now you can evaluate your flags anywhere in your code.

    user := ffcontext.NewEvaluationContext("user-unique-key")
    hasFlag, _ := ffclient.BoolVariation("test-flag", user, false)
    if hasFlag {
      // flag "test-flag" is true for the user
    } else {
      // flag "test-flag" is false for the user
    }

    The full documentation is available on https://docs.gofeatureflag.org
    You can find more examples in the examples/ directory.

    Can I use GO Feature Flag with any language?

    Originally GO Feature Flag was built to be a GOlang only library, but it limits the ecosystem too much.
    To be compatible with more languages we have implemented the GO Feature Flag Relay Proxy. It is a service you can host that provides an API to evaluate your flags, you can call it using HTTP to get your variation.

    Since we believe in standardization we are also implementing OpenFeature providers to interact with this API in the language of your choice.
    (OpenFeature is still at an early stage, so not all languages are supported and expect some changes in the future)

    For now, we have providers for:

    Language Provider Source Version
    Go Go Provider version
    Java / Kotlin (server) Java Provider version
    Android / Kotlin (client) Kotlin Provider version
    Javascript/Typescript (server) Server Provider version
    Javascript/Typescript (client) Client Provider version
    Python Python Provider version
    .Net .Net Provider version
    Ruby Ruby Provider version
    Swift Swift Provider version
    PHP PHP Provider version

    Where do I store my flags file?

    The module supports different ways of retrieving the flag file.
    The available retrievers are:

    • GitHub
    • GitLab
    • HTTP endpoint
    • AWS S3
    • Local file
    • Google Cloud Storage
    • Kubernetes ConfigMaps
    • MongoDB
    • Redis
    • BitBucket
    • AzBlobStorage
    • ...

    See the full list and more information.

    Flags file format

    GO Feature Flag core feature is to centralize all your feature flags in a single file and to avoid hosting and maintaining a backend server to manage them.

    Your file should be a YAML, JSON or TOML file with a list of flags (examples: YAML, JSON, TOML).

    The easiest way to create your configuration file is to use GO Feature Flag Editor available at https://editor.gofeatureflag.org.
    If you prefer to do it manually please follow the instruction below.

    A flag configuration looks like this:

    YAML
    # This is your configuration for your first flag
    first-flag:
      variations: # All possible return value for your feature flag
        A: false
        B: true
      targeting: # If you want to target a subset of your users in particular
        - query: key eq "random-key"
          percentage:
            A: 0
            B: 100
      defaultRule: # When no targeting match we use the defaultRule
        variation: A
    
    # A second example of a flag configuration
    second-flag:
      variations:
        A: <
    2925
    span class="pl-pds">"valueA"
        B: "valueB"
        defaultValue: "a default value"
      targeting:
        - name: notkey_rule
          query: key eq "not-a-key"
          percentage:
            A: 10
            B: 90
      defaultRule:
        variation: defaultValue
      version: "12"
      experimentation:
        start: 2021-03-20T00:00:00.1-05:00
        end: 2021-03-21T00:00:00.1-05:00
    JSON
    {
      "first-flag": {
        "variations": {
          "A": false,
          "B": true
        },
        "targeting": [
          {
            "query": "key eq \"random-key\"",
            "percentage": {
              "A": 0,
              "B": 100
            }
          }
        ],
        "defaultRule": {
          "variation": "A"
        }
      },
    
      "second-flag": {
        "variations": {
          "A": "valueA",
          "B": "valueB",
          "defaultValue": "a default value"
        },
        "targeting": [
          {
            "name": "notkey_rule",
            "query": "key eq \"not-a-key\"",
            "percentage": {
              "A": 10,
              "B": 90
            }
          }
        ],
        "defaultRule": {
          "variation": "defaultValue"
        },
        "version": "12",
        "experimentation": {
          "start": "2021-03-20T05:00:00.100Z",
          "end": "2021-03-21T05:00:00.100Z"
        }
      }
    }
    TOML
    [first-flag.variations]
    A = false
    B = true
    
    [[first-flag.targeting]]
    query = 'key eq "random-key"'
    
    [first-flag.targeting.percentage]
    A = 0
    B = 100
    
    [first-flag.defaultRule]
    variation = "A"
    
    [second-flag]
    version = "12"
    
    [second-flag.variations]
    A = "valueA"
    B = "valueB"
    defaultValue = "a default value"
    
    [[second-flag.targeting]]
    name = "notkey_rule"
    query = 'key eq "not-a-key"'
    
    [second-flag.targeting.percentage]
    A = 10
    B = 90
    
    [second-flag.defaultRule]
    variation = "defaultValue"
    
    [second-flag.experimentation]
    start = 2021-03-20T05:00:00.100Z
    end = 2021-03-21T05:00:00.100Z

    For detailed information on the fields required to create a flag, please refer to the documentation.

    Rule format

    The query format is based on the nikunjy/rules library.

    All the operations can be written in capitalized or lowercase (ex: eq or EQ can be used).
    Logical Operations supported are AND OR.

    Compare Expression and their definitions (a|b means you can use either one of the two a or b):

    eq|==: equals to 
    ne|!=: not equals to
    lt|<: less than 
    gt|>: greater than
    le|<=: less than equal to
    ge|>=: greater than equal to 
    co: contains 
    sw: starts with 
    ew: ends with
    in: in a list
    pr: present
    not: not of a logical expression
    

    Examples

    • Select a specific user: key eq "example@example.com"
    • Select all identified users: anonymous ne true
    • Select a user with a custom property: userId eq "12345"

    Evaluation Context

    An evaluation context in a feature flagging system is crucial for determining the output of a feature flag evaluation. It's a collection of pertinent data about the conditions under which the evaluation is being made. This data can be supplied through a mix of static information (server name, IP, etc ...) and dynamic inputs (information about the user performing the action, etc ...), along with state information that is implicitly carried through the execution of the program.

    When using GO Feature Flag, it's often necessary to personalize the experience for different users. This is where the concept of a targeting key comes into play. A targeting key is a unique identifier that represents the context of the evaluation (email, session id, a fingerprint or anything that is consistent), ensuring that they are consistently exposed to the same variation of a feature, even across multiple visits or sessions.

    For instance, GO Feature Flag ensures that in cases where a feature is being rolled out to a percentage of users, based on the targeting key, they will see the same variation each time they encounter the feature flag.

    The targeting key is a fundamental part of the evaluation context because it directly affects the determination of which feature variant is served to a particular user, and it maintains that continuity over time. To do so GO Feature Flag to do a hash to define if the flag can apply to this evaluation context or not.
    We recommend using a hash if possible.

    Feature flag targeting and rollouts are all determined by the user you pass to your evaluation calls.

    Custom bucketing

    In some cases, you might need to bucket users based on a different key, e.g. a teamId, so that users within the same team get exposed to the same flag variation and get a consistent experience.

    This can be achieved by defining the bucketingKey field in the flag configuration. When present, the value corresponding to the bucketingKey will be extracted from the attributes, and that value used for hashing and determining the outcome in place of the targetingKey.

    Variations

    Variations are the different values possible for a feature flag.
    GO Feature Flag can manage more than just boolean values; the value of your flag can be any of the following types:

    • bool
    • int
    • float
    • string
    • json array
    • json object

    Example

    Boolean result = featureFlagClient.getBooleanValue("your.feature.key", false, userContext);
    
    // this example is using the java SDK
    // result is now true or false depending on the setting of this boolean feature flag

    Variation methods take the feature flag key, an evaluation context, and a default value.

    Why do we need a default value? If we have any error during the evaluation of the flag, we will return the default value, you will always get a value return from the function and we will never throw an error.

    In the example, if the flag your.feature.key does not exist, the result will be false.
    Note that the result will always provide a usable value.

    Rollout

    A critical part of every new feature release is orchestrating the actual launch schedule between the Product, Engineering, and Marketing teams.

    Delivering powerful user experiences typically requires software teams to manage complex releases and make manual updates at inconvenient times.

    But it does not have to, having a complex rollout strategy allows you to have a lifecycle for your flags.

    Complex rollout strategy available

    Notifiers

    If you want to be informed when a flag has changed, you can configure a notifier.

    A notifier will send one notification to the targeted system to inform them that a new flag configuration has been loaded.

    โ„น๏ธ GO Feature Flag can handle more than one notifier at a time.

    Available notifiers are:

    • Slack
    • Webhook
    • Discord
    • Microsoft Teams

    Export data

    GO Feature Flag allows you to export data about the usage of your flags.
    It collects all variation events and can save these events in several locations:

    • Local file - create local files with the variation usages.
    • Log - use your logger to write the variation usages.
    • AWS S3 - export your variation usages to S3.
    • AWS Kinesis - publish your variation usages to AWS Kinesis Stream.
    • Google Cloud Storage - export your variation usages to Google Cloud Storage.
    • Webhook - export your variation usages by calling a webhook.
    • AWS SQS - export your variation usages by sending events to SQS.
    • Google PubSub - export your variation usages by publishing events to PubSub topic.

    Currently, we are supporting only feature events.
    It represents individual flag evaluations and is considered "full fidelity" events.

    An example feature event below:

    {
      "kind": "feature",
      "contextKind": "anonymousUser",
      "userKey": "ABCD",
      "creationDate": 1618228297,
      "key": "test-flag",
      "variation": "Default",
      "value": false,
      "default": false,
      "source": "SERVER"
    }

    The format of the data is described in the documentation. Events are collected and sent in bulk to avoid spamming your exporter.

    Linter

    A command line tool is available to help you lint your configuration file: go-feature-flag-lint.

    How can I contribute?

    This project welcomes contributions from the community. If you're interested in contributing, see the contributors' guide for some helpful tips.

    Contributors

    Thanks so much to our contributors.

    Sponsors

    Become a sponsor and show your support to GO Feature Flag.

    These are our really cool sponsors!
    User avatar: SwisscomUser avatar: CybozuUser avatar: AltaModa Technologies

    Adopters

    If you are using go-feature-flag, we encourage you to include your company's name in this list. This simple act significantly boosts the project's visibility and credibility, making a substantial contribution to its advancement. To do so, kindly add yourself to adopters.

    Here is the list of adopters.

    0