{"id":13413824,"url":"https://github.com/thomaspoignant/go-feature-flag","last_synced_at":"2026-05-15T20:06:14.347Z","repository":{"id":37245571,"uuid":"320579524","full_name":"thomaspoignant/go-feature-flag","owner":"thomaspoignant","description":"GO Feature Flag is a simple, complete and lightweight self-hosted feature flag solution 100% Open Source. 🎛️","archived":false,"fork":false,"pushed_at":"2025-05-12T18:37:49.000Z","size":112578,"stargazers_count":1643,"open_issues_count":22,"forks_count":163,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-12T19:49:02.045Z","etag":null,"topics":["beginner-friendly","continuous-delivery","continuous-deployment","continuous-testing","devops","experimentation","experiments","feature-flag","feature-flags","feature-toggle","feature-toggles","feature-toggling","go","go-feature-flag","golang","golang-library","help-wanted","toggles","variants"],"latest_commit_sha":null,"homepage":"https://gofeatureflag.org/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thomaspoignant.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"thomaspoignant"}},"created_at":"2020-12-11T13:19:17.000Z","updated_at":"2025-05-12T18:34:41.000Z","dependencies_parsed_at":"2023-11-06T05:26:30.589Z","dependency_job_id":"50c7964b-4f23-4aa3-86dc-b2bfa73d7eac","html_url":"https://github.com/thomaspoignant/go-feature-flag","commit_stats":{"total_commits":506,"total_committers":19,"mean_commits":26.63157894736842,"dds":0.6284584980237153,"last_synced_commit":"d4424b0d5803ddd6af1dcff83f729e95a66acaf2"},"previous_names":[],"tags_count":168,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomaspoignant%2Fgo-feature-flag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomaspoignant%2Fgo-feature-flag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomaspoignant%2Fgo-feature-flag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomaspoignant%2Fgo-feature-flag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thomaspoignant","download_url":"https://codeload.github.com/thomaspoignant/go-feature-flag/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253813942,"owners_count":21968554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beginner-friendly","continuous-delivery","continuous-deployment","continuous-testing","devops","experimentation","experiments","feature-flag","feature-flags","feature-toggle","feature-toggles","feature-toggling","go","go-feature-flag","golang","golang-library","help-wanted","toggles","variants"],"created_at":"2024-07-30T20:01:50.391Z","updated_at":"2026-01-30T20:03:54.237Z","avatar_url":"https://github.com/thomaspoignant.png","language":"Go","funding_links":["https://github.com/sponsors/thomaspoignant"],"categories":["Server Applications","服务器应用程序","Go","Relational Databases","\u003ca name=\"Go\"\u003e\u003c/a\u003eGo"],"sub_categories":["HTTP Clients","HTTP客户端"],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://gofeatureflag.org\" target=\"_blank\"\u003e\u003cimg width=\"400\" src=\"gofeatureflag.svg\" alt=\"go-feature-flag logo\" /\u003e\u003c/a\u003e\n  \u003c!-- \u003ca href=\"https://gofeatureflag.org\" target=\"_blank\"\u003e\u003cimg src=\"website/static/img/logo/logo_footer.png?raw=true\" alt=\"go-feature-flag logo\" /\u003e\u003c/a\u003e --\u003e\n\u003c/p\u003e\n\n# 🎛️ GO Feature Flag\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/thomaspoignant/go-feature-flag/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/thomaspoignant/go-feature-flag/actions/workflows/ci.yml/badge.svg\" alt=\"Build Status\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://scorecard.dev/viewer/?uri=github.com/thomaspoignant/go-feature-flag\"\u003e\u003cimg src=\"https://api.scorecard.dev/projects/github.com/thomaspoignant/go-feature-flag/badge\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/thomaspoignant/go-feature-flag\"\u003e\u003cimg src=\"https://codecov.io/gh/thomaspoignant/go-feature-flag/branch/main/graph/badge.svg?token=T59ACQWW1H\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://sonarcloud.io/dashboard?id=thomaspoignant_go-feature-flag\"\u003e\u003cimg src=\"https://sonarcloud.io/api/project_badges/measure?project=thomaspoignant_go-feature-flag\u0026metric=alert_status\" alt=\"Sonarcloud Status\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/thomaspoignant/go-feature-flag/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/thomaspoignant/go-feature-flag?filter=v*\" alt=\"Release version\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/thomaspoignant/go-feature-flag\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/thomaspoignant/go-feature-flag\" alt=\"Build Status\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/thomaspoignant/go-feature-flag/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/thomaspoignant/go-feature-flag\" alt=\"License\"/\u003e\u003c/a\u003e\n    \u003cbr/\u003e\n    \u003ca href=\"https://www.bestpractices.dev/projects/6290\"\u003e\u003cimg src=\"https://www.bestpractices.dev/projects/6290/badge\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag\"\u003e\u003cimg src=\"https://godoc.org/github.com/thomaspoignant/go-feature-flag?status.svg\" alt=\"GoDoc\" /\u003e\u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/github/go-mod/go-version/thomaspoignant/go-feature-flag?logo=go%20version\" alt=\"Go version\"/\u003e\n    \u003ca href=\"https://github.com/avelino/awesome-go/#server-applications\"\u003e\u003cimg src=\"https://awesome.re/mentioned-badge.svg\" alt=\"Mentioned in Awesome Go\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://gofeatureflag.org/slack\"\u003e\u003cimg src=\"https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true\u0026logo=slack\u0026colorB=green\" alt=\"Join us on slack\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/sponsors/thomaspoignant\"\u003e\u003cimg src=\"https://img.shields.io/github/sponsors/thomaspoignant?logo=GitHub%20Sponsors\" alt=\"Sponsords\"\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://gofeatureflag.org\"\u003eGO Feature Flag is a simple, complete and lightweight self-hosted feature flag solution 100% Open Source.\u003c/a\u003e\n\u003c/p\u003e\n\n\u003e :pray: If you are using **GO Feature Flag** please consider to add yourself in the [adopters](./ADOPTERS.md) list.  \n\u003e This simple act significantly boosts the project's visibility and credibility, making a substantial contribution to its advancement.\n\u003e \n\u003e If you want to support me and GO Feature Flag, you can also [become a sponsor](https://github.com/sponsors/thomaspoignant).\n\n## Table of Contents\n\n- [🎛️ GO Feature Flag](#️-go-feature-flag)\n  - [What is GO Feature Flag?](#what-is-go-feature-flag)\n  - [What can I do with GO Feature Flag?](#what-can-i-do-with-go-feature-flag)\n  - [Part of the OpenFeature Ecosystem](#part-of-the-openFeature-ecosystem)\n  - [Getting started with GO Feature Flag](#getting-started)\n  - [Can I use GO Feature Flag with any language?](#can-i-use-go-feature-flag-with-any-language)\n  - [Where do I store my flags file?](#where-do-i-store-my-flags-file)\n  - [Flags file format](#flags-file-format)\n  - [Rule format](#rule-format)\n  - [Evaluation Context](#evaluation-context)\n  - [Variations](#variations)\n  - [Rollout](#rollout)\n    - [Complex rollout strategy available](#complex-rollout-strategy-available)\n  - [Notifiers](#notifiers)\n  - [Export data](#export-data)\n  - [Linter](#linter)\n- [How can I contribute?](#how-can-i-contribute)\n  - [Contributors](#contributors)\n  - [Sponsors](#sponsors)\n  - [Adopters](#adopters)\n\n## What is GO Feature Flag?\n\nGO Feature Flag is a lightweight and open-source solution that provides a simple and complete feature flag implementation.\n\nThe solution has been built to facilitate the usage of feature flags in your code with the easiest setup possible.\n\nOriginally, **GO Feature Flag** was designed as a solution exclusively for the `GO` language. With the new standardization of feature flags by the [Openfeature](https://openfeature.dev/) project, the solution is now available for multiple languages _([list of supported languages](https://gofeatureflag.org/docs/sdk))_ through a simple API server called the relay proxy, which can be hosted.\n\n\u003e [!TIP]\n\u003e If you are not familiar with feature flags, I've written an [article](https://medium.com/better-programming/feature-flags-and-how-to-iterate-quickly-7e3371b9986) which explains why feature flags can fasten your iteration cycle.\n\n## What can I do with GO Feature Flag?\n\n- Use the feature flag standard [OpenFeature](https://openfeature.dev) in your favorite language _([see list](#can-i-use-go-feature-flag-with-any-language))_.\n- Storing your configuration flags file on various locations (`HTTP`, `S3`, `Kubernetes`, [_see full list_](https://gofeatureflag.org/docs/configure_flag/store_your_flags)).\n- Configuring your flags in various [format](https://gofeatureflag.org/docs/configure_flag/flag_format) (`JSON`, `TOML` and `YAML`).\n- Adding complex [rules](https://gofeatureflag.org/docs/configure_flag/target-with-flags) to target your users.\n- Use a complex rollout strategy for your flags :\n  - [Run A/B testing experimentation](https://gofeatureflag.org/docs/configure_flag/rollout-strategies/experimentation).\n  - [Progressively rollout a feature](https://gofeatureflag.org/docs/configure_flag/rollout-strategies/progressive).\n  - [Schedule your flag updates](https://gofeatureflag.org/docs/configure_flag/rollout-strategies/scheduled).\n- Exporting your flags usage data to various destinations such as _(`S3`, `Google cloud storage`, `file`, `kubernetes`, see the [_full list_](https://gofeatureflag.org/docs/integrations/store-flags-configuration#available-retrievers))_.\n- Getting notified when a flag has been changed _(`webhook` and `slack`)_.\n- Support your full stack, from the backend to the frontend including your mobile apps.\n\nhttps://github.com/user-attachments/assets/56e1a2a2-996f-4db8-9c93-28c057e4ed5a\n\n_The code of this demo is available in [`examples/demo`](examples/demo) repository_.\n\n## Part of the OpenFeature Ecosystem\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/thomaspoignant/go-feature-flag/cab0bbc294e77a0a0afff64fd499ff691bb0b792/website/static/img/features/openfeature.svg\" width=\"340\" /\u003e\n\u003c/p\u003e\n\nAt 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.\n\nBy adopting GO Feature Flag you embrace the OpenFeature standard and you get all the benefits of the ecosystem.\n\n- Open-Source standard SDKs\n- No Vendor Lock-In\n- OpenFeature community based support for SDKs\n\n## Getting started\n\n\u003e [!IMPORTANT]\n\u003e Before starting to use **GO Feature Flag** you should decide\n\u003e if you want to use Open Feature SDKs or if you want to use GO Feature Flag as a GO Module.\n\u003e \n\u003e We recommend using the relay-proxy for a central flag management and evaluation solution,\n\u003e it enables the multi-languages support, and it integrates seamlessly with the Open Feature SDKs.  \n\u003e This is the best way to get full potential of GO Feature Flag.\n\u003e \n\u003e If your project is exclusively in GO, the GO module is an option. It will perform the flag evaluation directly in your GO code.\n\n\u003ca id=\"using-open-feature\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eUsing Open Feature SDKs\u003c/b\u003e\u003c/summary\u003e\n\n### Create a feature flag configuration\n\nCreate a new `YAML` file containing your first flag configuration.\n\n```yaml title=\"flag-config.yaml\"\n# 20% of the users will use the variation \"my-new-feature\"\ntest-flag:\n  variations:\n    my-new-feature: true\n    my-old-feature: false\n  defaultRule:\n    percentage:\n      my-new-feature: 20\n      my-old-feature: 80\n```\n\nThis flag split the usage of this flag, 20% will use the variation `my-new-feature` and 80% the variation `my-old-feature`.\n\n### Create a relay proxy configuration file\n\nCreate a new `YAML` file containing the configuration of your relay proxy.\n\n```yaml title=\"goff-proxy.yaml\"\nserver:\n  mode: http\n  port: 1031\npollingInterval: 1000\nstartWithRetrieverError: false\nretriever:\n  kind: file\n  path: /goff/flag-config.yaml\nexporter:\n  kind: log\n```\n\n### Install the relay proxy\n\nAnd we will run the **relay proxy** locally to make the API available.  \nThe default port will be `1031`.\n\n```shell\n# Launch the container\ndocker run \\\n  -p 1031:1031 \\\n  -v $(pwd)/flag-config.yaml:/goff/flag-config.yaml \\\n  -v $(pwd)/goff-proxy.yaml:/goff/goff-proxy.yaml \\\n  gofeatureflag/go-feature-flag:latest\n\n```\n\n_If you don't want to use docker to install the **relay proxy** you can follow other ways to install it in the [documentation](https://gofeatureflag.org/docs/relay-proxy/install_relay_proxy)._\n\n### Use Open Feature SDK\n\n_In this example, we are using the **nodejs SDK**, but you can check other languages [here](https://gofeatureflag.org/docs/sdk)._\n\n\n#### Install dependencies\n\n```shell\nnpm i @openfeature/server-sdk @openfeature/go-feature-flag-provider\n```\n\n#### Init your Open Feature client\n\nIn your app initialization, you have to create a client using the Open Feature SDK and initialize it.\n\n```javascript\nconst {OpenFeature} = require(\"@openfeature/server-sdk\");\nconst {GoFeatureFlagProvider} = require(\"@openfeature/go-feature-flag-provider\");\n\n\n// init Open Feature SDK with GO Feature Flag provider\nconst goFeatureFlagProvider = new GoFeatureFlagProvider({\n  endpoint: 'http://localhost:1031/' // DNS of your instance of relay proxy\n});\nOpenFeature.setProvider(goFeatureFlagProvider);\nconst featureFlagClient = OpenFeature.getClient('my-app')\n```\n\n#### Evaluate your flag\n\nNow you can evaluate your flags anywhere in your code using this client.\n\n```javascript\n// Context of your flag evaluation.\n// With GO Feature Flag you MUST provide a targetingKey that is a unique identifier of the user.\nconst evaluationContext = {\n  targetingKey: '1d1b9238-2591-4a47-94cf-d2bc080892f1', // user unique identifier (mandatory)\n  firstname: 'john',\n  lastname: 'doe',\n  email: 'john.doe@gofeatureflag.org',\n  admin: true, // this field is used in the targeting rule of the flag \"flag-only-for-admin\"\n  // ...\n};\n\nconst adminFlag = await featureFlagClient.getBooleanValue('flag-only-for-admin', false, evaluationContext);\nif (adminFlag) {\n  // flag \"flag-only-for-admin\" is true for the user\n  console.log(\"new feature\");\n} else {\n  // flag \"flag-only-for-admin\" is false for the user\n}\n```\n\n\u003c/details\u003e\n\n\u003ca id=\"using-go-module\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eUsing the GO Module\u003c/b\u003e\u003c/summary\u003e\n\n### Installation\n```bash\ngo get github.com/thomaspoignant/go-feature-flag\n```\n\n### Create a feature flag configuration\n\nCreate a new `YAML` file containing your first flag configuration.\n\n```yaml title=\"flag-config.yaml\"\n# 20% of the users will use the variation \"my-new-feature\"\ntest-flag:\n  variations:\n    my-new-feature: true\n    my-old-feature: false\n  defaultRule:\n    percentage:\n      my-new-feature: 20\n      my-old-feature: 80\n```\n\nThis flag split the usage of this flag, 20% will use the variation `my-new-feature` and 80% the variation `my-old-feature`.\n\n### SDK Initialisation\nFirst, you need to initialize the `ffclient` with the location of your backend file.\n```go linenums=\"1\"\nerr := ffclient.Init(ffclient.Config{\n  PollingInterval: 3 * time.Second,\n  Retriever:      \u0026fileretriever.Retriever{\n    Path: \"flag-config.goff.yaml\",\n  },\n})\ndefer ffclient.Close()\n```\n*This example will load a file from your local computer and will refresh the flags every 3 seconds (if you omit the\nPollingInterval, the default value is 60 seconds).*\n\n\u003e ℹ info  \nThis is a basic configuration to test locally, in production it is better to use a remote place to store your feature flag configuration file.  \nLook at the list of available options in the [**Store your feature flag file** page](https://gofeatureflag.org/docs/integrations/store-flags-configuration#available-retrievers).\n\n### Evaluate your flags\nNow you can evaluate your flags anywhere in your code.\n\n```go linenums=\"1\"\nuser := ffcontext.NewEvaluationContext(\"user-unique-key\")\nhasFlag, _ := ffclient.BoolVariation(\"test-flag\", user, false)\nif hasFlag {\n  // flag \"test-flag\" is true for the user\n} else {\n  // flag \"test-flag\" is false for the user\n}\n```\nThe full documentation is available on https://docs.gofeatureflag.org  \nYou can find more examples in the [examples/](https://github.com/thomaspoignant/go-feature-flag/tree/main/examples) directory.\n\n\u003c/details\u003e\n\n## Can I use GO Feature Flag with any language?\n\nOriginally GO Feature Flag was built to be a GOlang only library, but it limits the ecosystem too much.  \nTo be compatible with more languages we have implemented the [GO Feature Flag Relay Proxy](cmd/relayproxy/).\nIt is a service you can host that provides an API to evaluate your flags, you can call it using HTTP to get your variation.\n\nSince we believe in standardization we are also implementing [OpenFeature](https://github.com/open-feature) providers to interact with this API in the language of your choice.  \n_(OpenFeature is still at an early stage, so not all languages are supported and expect some changes in the future)_\n\nFor now, we have providers for:\n\n| Language                       | Provider Source                                                                                                               | Version                                                                                                                                                                                                                                                                                                                                   |\n|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Go                             | [Go Provider](https://github.com/open-feature/go-sdk-contrib/tree/main/providers/go-feature-flag)                             | [![version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fproxy.golang.org%2Fgithub.com%2Fopen-feature%2Fgo-sdk-contrib%2Fproviders%2Fgo-feature-flag%2F%40latest\u0026query=%24.Version\u0026label=GO\u0026color=blue\u0026style=flat-square\u0026logo=golang)](https://github.com/open-feature/go-sdk-contrib/tree/main/providers/go-feature-flag) |\n| Java / Kotlin (server)         | [Java Provider](https://github.com/open-feature/java-sdk-contrib/tree/main/providers/go-feature-flag)                         | [![version](https://img.shields.io/maven-central/v/dev.openfeature.contrib.providers/go-feature-flag?color=blue\u0026style=flat-square\u0026logo=java)](https://central.sonatype.com/artifact/dev.openfeature.contrib.providers/go-feature-flag)                                                                                                    |\n| Android / Kotlin (client)      | [Kotlin Provider](openfeature/providers/kotlin-provider)                                                                      | [![version](https://img.shields.io/maven-central/v/org.gofeatureflag.openfeature/gofeatureflag-kotlin-provider?color=blue\u0026style=flat-square\u0026logo=android)](https://central.sonatype.com/artifact/org.gofeatureflag.openfeature/gofeatureflag-kotlin-provider)                                                                             |                                                                                                    \n| Javascript/Typescript (server) | [Server Provider](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/go-feature-flag)                    | [![version](https://img.shields.io/npm/v/%40openfeature%2Fgo-feature-flag-provider?color=blue\u0026style=flat-square\u0026logo=npm)](https://www.npmjs.com/package/@openfeature/go-feature-flag-provider)                                                                                                                                           |\n| Javascript/Typescript (client) | [Client Provider](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/go-feature-flag-web)                | [![version](https://img.shields.io/npm/v/%40openfeature%2Fgo-feature-flag-web-provider?color=blue\u0026style=flat-square\u0026logo=npm)](https://www.npmjs.com/package/@openfeature/go-feature-flag-web-provider)                                                                                                                                   |\n| Python                         | [Python Provider](openfeature/providers/python-provider)                                                                      | [![version](https://img.shields.io/pypi/v/gofeatureflag-python-provider?color=blue\u0026style=flat-square\u0026logo=pypi)](https://pypi.org/project/gofeatureflag-python-provider/)                                                                                                                                                                 |\n| .NET                           | [.NET Provider](https://github.com/open-feature/dotnet-sdk-contrib/tree/main/src/OpenFeature.Providers.GOFeatureFlag) | [![version](https://img.shields.io/nuget/v/OpenFeature.Providers.GOFeatureFlag?color=blue\u0026style=flat-square\u0026logo=nuget)](https://nuget.info/packages/OpenFeature.Providers.GOFeatureFlag)                                                                                                                                                     |\n| Ruby                           | [Ruby Provider](https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-go-feature-flag-provider)    | [![version](https://img.shields.io/gem/v/openfeature-go-feature-flag-provider?color=blue\u0026style=flat-square\u0026logo=ruby)](https://rubygems.org/gems/openfeature-go-feature-flag-provider)                                                                                                                                                    |\n| Swift                          | [Swift Provider](https://github.com/go-feature-flag/openfeature-swift-provider)                                               | [![version](https://img.shields.io/github/v/release/go-feature-flag/openfeature-swift-provider?label=Swift\u0026amp;display_name=tag\u0026style=flat-square\u0026logo=Swift)](https://github.com/go-feature-flag/openfeature-swift-provider)                                                                                                             |\n| PHP                            | [PHP Provider](https://github.com/open-feature/php-sdk-contrib/tree/main/providers/GoFeatureFlag)                             | [![version](https://img.shields.io/packagist/v/open-feature/go-feature-flag-provider?logo=php\u0026color=blue\u0026style=flat-square)](https://packagist.org/packages/open-feature/go-feature-flag-provider)                                                                                                                                                 |\n                                                                                                                                                                                                                                        \n\n## Where do I store my flags file?\n\nThe module supports different ways of retrieving the flag file.  \nThe available retrievers are:\n- **GitHub**\n- **GitLab**\n- **HTTP endpoint**\n- **AWS S3**\n- **Local file**\n- **Google Cloud Storage**\n- **Kubernetes ConfigMaps**\n- **MongoDB**\n- **Redis**\n- **BitBucket**\n- **AzBlobStorage**\n- ...\n\n_[See the full list and more information.](https://gofeatureflag.org/docs/integrations/store-flags-configuration#available-retrievers)_\n\n## Flags file format\n**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.\n\nYour file should be a `YAML`, `JSON` or `TOML` file with a list of flags *(examples: [`YAML`](testdata/flag-config.yaml), [`JSON`](testdata/flag-config.json), [`TOML`](testdata/flag-config.toml))*.\n\nThe easiest way to create your configuration file is to use **GO Feature Flag Editor** available at https://editor.gofeatureflag.org.  \nIf you prefer to do it manually please follow the instruction below.\n\n**A flag configuration looks like this:**\n\n\u003cdetails open\u003e\n\u003csummary\u003eYAML\u003c/summary\u003e\n\n```yaml\n# This is your configuration for your first flag\nfirst-flag:\n  variations: # All possible return value for your feature flag\n    A: false\n    B: true\n  targeting: # If you want to target a subset of your users in particular\n    - query: key eq \"random-key\"\n      percentage:\n        A: 0\n        B: 100\n  defaultRule: # When no targeting match we use the defaultRule\n    variation: A\n\n# A second example of a flag configuration\nsecond-flag:\n  variations:\n    A: \"valueA\"\n    B: \"valueB\"\n    defaultValue: \"a default value\"\n  targeting:\n    - name: notkey_rule\n      query: key eq \"not-a-key\"\n      percentage:\n        A: 10\n        B: 90\n  defaultRule:\n    variation: defaultValue\n  version: \"12\"\n  experimentation:\n    start: 2021-03-20T00:00:00.1-05:00\n    end: 2021-03-21T00:00:00.1-05:00\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eJSON\u003c/summary\u003e\n\n```json\n{\n  \"first-flag\": {\n    \"variations\": {\n      \"A\": false,\n      \"B\": true\n    },\n    \"targeting\": [\n      {\n        \"query\": \"key eq \\\"random-key\\\"\",\n        \"percentage\": {\n          \"A\": 0,\n          \"B\": 100\n        }\n      }\n    ],\n    \"defaultRule\": {\n      \"variation\": \"A\"\n    }\n  },\n\n  \"second-flag\": {\n    \"variations\": {\n      \"A\": \"valueA\",\n      \"B\": \"valueB\",\n      \"defaultValue\": \"a default value\"\n    },\n    \"targeting\": [\n      {\n        \"name\": \"notkey_rule\",\n        \"query\": \"key eq \\\"not-a-key\\\"\",\n        \"percentage\": {\n          \"A\": 10,\n          \"B\": 90\n        }\n      }\n    ],\n    \"defaultRule\": {\n      \"variation\": \"defaultValue\"\n    },\n    \"version\": \"12\",\n    \"experimentation\": {\n      \"start\": \"2021-03-20T05:00:00.100Z\",\n      \"end\": \"2021-03-21T05:00:00.100Z\"\n    }\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eTOML\u003c/summary\u003e\n\n```toml\n[first-flag.variations]\nA = false\nB = true\n\n[[first-flag.targeting]]\nquery = 'key eq \"random-key\"'\n\n[first-flag.targeting.percentage]\nA = 0\nB = 100\n\n[first-flag.defaultRule]\nvariation = \"A\"\n\n[second-flag]\nversion = \"12\"\n\n[second-flag.variations]\nA = \"valueA\"\nB = \"valueB\"\ndefaultValue = \"a default value\"\n\n[[second-flag.targeting]]\nname = \"notkey_rule\"\nquery = 'key eq \"not-a-key\"'\n\n[second-flag.targeting.percentage]\nA = 10\nB = 90\n\n[second-flag.defaultRule]\nvariation = \"defaultValue\"\n\n[second-flag.experimentation]\nstart = 2021-03-20T05:00:00.100Z\nend = 2021-03-21T05:00:00.100Z\n```\n\n\u003c/details\u003e\n\nFor detailed information on the fields required to create a flag, please refer to the [documentation](https://gofeatureflag.org/docs/configure_flag/create-flags).\n\n## Rule format\n\nThe query format is based on the [`nikunjy/rules`](https://github.com/nikunjy/rules) library.\n\nAll the operations can be written in capitalized or lowercase (ex: `eq` or `EQ` can be used).  \nLogical Operations supported are `AND` `OR`.\n\nCompare Expression and their definitions (`a|b` means you can use either one of the two `a` or `b`):\n\n```\neq|==: equals to \nne|!=: not equals to\nlt|\u003c: less than \ngt|\u003e: greater than\nle|\u003c=: less than equal to\nge|\u003e=: greater than equal to \nco: contains \nsw: starts with \new: ends with\nin: in a list\npr: present\nnot: not of a logical expression\n```\n### Examples\n\n- Select a specific user: `key eq \"example@example.com\"`\n- Select all identified users: `anonymous ne true`\n- Select a user with a custom property: `userId eq \"12345\"`\n\n## Evaluation Context\nAn 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.\n\nWhen 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.\n\nFor 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.\n\nThe 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.  \n**We recommend using a hash if possible.**   \n\nFeature flag targeting and rollouts are all determined by the user you pass to your evaluation calls.\n\n## Custom bucketing\n\nIn 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.\n\nThis 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`.\n\n## Variations\nVariations are the different values possible for a feature flag.  \nGO Feature Flag can manage more than just `boolean` values; the value of your flag can be any of the following types:\n- `bool`\n- `int`\n- `float`\n- `string`\n- `json array`\n- `json object`\n\n### Example\n```java\nBoolean result = featureFlagClient.getBooleanValue(\"your.feature.key\", false, userContext);\n\n// this example is using the java SDK\n// result is now true or false depending on the setting of this boolean feature flag\n```\nVariation methods take the feature **flag key**, an **evaluation context**, and a **default value**.\n\n**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.\n\nIn the example, if the flag `your.feature.key` does not exist, the result will be `false`.  \nNote that the result will always provide a usable value.\n\n## Rollout\n\nA critical part of every new feature release is orchestrating the actual launch schedule between the Product, Engineering, and Marketing teams.\n\nDelivering powerful user experiences typically requires software teams to manage complex releases and make manual updates at inconvenient times.\n\nBut it does not have to, having a complex **rollout** strategy allows you to have a lifecycle for your flags.\n\n### Complex rollout strategy available\n\n- [Percentages rollout](https://gofeatureflag.org/docs/configure_flag/rollout-strategies/percentage) - impact randomly a subset of your users.\n- [Progressive rollout](https://gofeatureflag.org/docs/configure_flag/rollout-strategies/progressive) - increase the percentage of your flag over time.\n- [Scheduled rollout](https://gofeatureflag.org/docs/configure_flag/rollout-strategies/scheduled) - update your flag over time.\n- [Experimentation rollout](https://gofeatureflag.org/docs/configure_flag/rollout-strategies/experimentation) - serve your feature only for a determined time *(perfect for A/B testing)*.\n\n## Notifiers\nIf you want to be informed when a flag has changed, you can configure a [**notifier**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#NotifierConfig).\n\nA notifier will send one notification to the targeted system to inform them that a new flag configuration has been loaded.\n\nℹ️ **GO Feature Flag** can handle more than one notifier at a time.\n\nAvailable notifiers are:\n- **Slack**\n- **Webhook**\n- **Discord**\n- **Microsoft Teams**\n\n## Export data\n**GO Feature Flag** allows you to export data about the usage of your flags.    \nIt collects all variation events and can save these events in several locations:\n\n- **Local file** *- create local files with the variation usages.*\n- **Log** *- use your logger to write the variation usages.*\n- **AWS S3** *- export your variation usages to S3.*\n- **AWS Kinesis** *- publish your variation usages to AWS Kinesis Stream.*\n- **Google Cloud Storage** *- export your variation usages to Google Cloud Storage.*\n- **Webhook** *- export your variation usages by calling a webhook.*\n- **AWS SQS** *- export your variation usages by sending events to SQS.*\n- **Google PubSub** *- export your variation usages by publishing events to PubSub topic.*\n\nCurrently, we are supporting only feature events.  \nIt represents individual flag evaluations and is considered \"full fidelity\" events.\n\n**An example feature event below:**\n```json\n{\n  \"kind\": \"feature\",\n  \"contextKind\": \"anonymousUser\",\n  \"userKey\": \"ABCD\",\n  \"creationDate\": 1618228297,\n  \"key\": \"test-flag\",\n  \"variation\": \"Default\",\n  \"value\": false,\n  \"default\": false,\n  \"source\": \"SERVER\"\n}\n```\nThe format of the data is [described in the documentation](https://gofeatureflag.org/docs/).\nEvents are collected and sent in bulk to avoid spamming your exporter.\n\n## Linter\nA command line tool is available to help you lint your configuration file: [go-feature-flag-lint](cmd/cli/README.md).\n\n# How can I contribute?\n\nThis project welcomes contributions from the community. If you're interested in contributing, see the [contributors' guide](CONTRIBUTING.md) for some helpful tips.\n\n## Contributors\n\nThanks so much to our contributors.\n\n\u003ca href=\"https://github.com/thomaspoignant/go-feature-flag/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=thomaspoignant/go-feature-flag\" /\u003e\n\u003c/a\u003e\n\n## Sponsors\n\n[Become a sponsor](https://github.com/sponsors/thomaspoignant) and show your support to GO Feature Flag.\n\nThese are our really cool sponsors!  \n\u003ca href=\"https://github.com/swisscom\"\u003e\u003cimg src=\"https:\u0026#x2F;\u0026#x2F;github.com\u0026#x2F;swisscom.png\" width=\"60px\" alt=\"User avatar: Swisscom\" /\u003e\u003c/a\u003e\u003c!-- sponsors --\u003e\u003ca href=\"https://github.com/cybozu\"\u003e\u003cimg src=\"https:\u0026#x2F;\u0026#x2F;github.com\u0026#x2F;cybozu.png\" width=\"60px\" alt=\"User avatar: Cybozu\" /\u003e\u003c/a\u003e\u003ca href=\"https://github.com/AltaModaTech\"\u003e\u003cimg src=\"https:\u0026#x2F;\u0026#x2F;github.com\u0026#x2F;AltaModaTech.png\" width=\"60px\" alt=\"User avatar: AltaModa Technologies\" /\u003e\u003c/a\u003e\u003c!-- sponsors --\u003e\n\n## Adopters\n\nIf 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](./ADOPTERS.md).\n\nHere is the list of [adopters](./ADOPTERS.md).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomaspoignant%2Fgo-feature-flag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomaspoignant%2Fgo-feature-flag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomaspoignant%2Fgo-feature-flag/lists"}