XUtils

go-feature-flag

A simple, complete and lightweight self-hosted feature flag solution 100% Open Source.


Getting started

Before starting to use GO Feature Flag you should decide if you want to use the GO Module directly or if you want to install the relay proxy.

The GO module is ideal for using GO Feature Flag exclusively in GO projects. If your project involves multiple languages, we recommend using the Open Feature SDKs.

Using the GO Module

Create a feature flag configuration

Create a new YAML file containing your first flag configuration.

”`yaml title=“flag-config.yaml”

SDK Initialisation

First, you need to initialize the ffclient with the location of your backend file. “`go linenums=“1” 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](https://gofeatureflag.org/docs/go_module/store_file/).

### Evaluate your flags
Now you can evaluate your flags anywhere in your code.

```go linenums="1"
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.

Using Open Feature SDKs

Create a feature flag configuration

Create a new YAML file containing your first flag configuration.

”`yaml title=“flag-config.yaml”

Create a relay proxy configuration file

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

”`yaml title=“goff-proxy.yaml” listen: 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`.

```shell
# 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 go to docker hub.

Use Open Feature SDK

In this example, we are using the javascript SDK, but it is still relevant for all the languages.

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 have a targetingKey that is a unique identifier of the user.
const userContext = {
  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, userContext);
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
}

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 ```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: "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 ```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 ```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.

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"

Users

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

The only required field for a user is his unique key, it is used by the internals of GO Feature Flag to do a hash to define if the flag can apply to this user or not. You can use a primary key, an e-mail address, or a hash, as long as the same user always has the same key.
We recommend using a hash if possible.
All the other attributes are optional.

Since it is useful to make complex queries on your flag, you can add as many information fields you want to your user. It will be used when testing the targeting rules.

You can also distinguish logged-in users from anonymous users in the SDK (check documentation about anonymous users).

Variations

The Variation methods determine whether a flag is enabled or not for a specific user.

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

”`go linenums=“1” result, _ := ffclient.BoolVariation(“your.feature.key”, user, false)

// result is now true or false depending on the setting of // this boolean feature flag “` Variation methods take the feature flag key, a user, and a default value.

The default value is returned when an error is encountered (ffclient not initialized, variation with wrong type, flag does not exist …).

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.

Get all flags for a specific user

If you want to send the information about a specific user to a front-end, you will want a snapshot of all the flags for this user at a specific time.

The method ffclient.AllFlagsState returns a snapshot of flag values and metadata.
The function is evaluating all available flags for the user and returns a flagstate.AllFlagsState object containing the information you need.

The MarshalJSON() function will return a JSON Object, that can be directly used by your front-end application.
More details in the documentation.

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

Linter

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

Contributors

Thanks so much to our contributors.

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.


Articles

  • coming soon...