GO Feature Flag: a self-hosted flag server for OpenFeature SDKs
Project brief: GO Feature Flag is a simple, complete and lightweight self-hosted cloud native feature flag solution 100% Open Source, built on OpenFeature.
At a glance
- What is it?
- GO Feature Flag stores flags in JSON, YAML or TOML files and evaluates them either inside a Go process or through a relay proxy that any OpenFeature SDK can call. The relay proxy is the part that decides whether this fits you.
- Who is it for?
- Adopt GO Feature Flag if you want flag definitions in version-controlled files and you are willing to run the relay proxy so non-Go services can use the same flags. Do not adopt it if you need a hosted UI with approval workflows and audit trails, or if nobody on the team can own a config file and a proxy deployment.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What GO Feature Flag replaces, and for whom
The project targets teams that want feature flags without a SaaS vendor in the request path. Flag definitions live in files (JSON, TOML or YAML) that you host wherever you already keep configuration: HTTP, S3, a Kubernetes ConfigMap, MongoDB, GitHub, and others listed in the documentation's store-your-flags page. There is no separate flag database to operate.
The audience is narrower than the tagline suggests. The repository began as a Go-only library, and the README states that the relay proxy was added so that other languages could reach the same evaluation logic. So there are two distinct users here: a Go service that can import the module and evaluate flags in-process, and everything else (Node, Kotlin, Swift, React, browser code) that talks to the relay proxy over its API. If your stack is polyglot, the proxy is not optional, it is the product.
The trade-off is explicit. In-process evaluation in Go removes a network hop and a process to run, but it also means each service reads the flag file itself and you lose one central place to change flags. The proxy gives you that central point and multi-language support, at the cost of one more deployment and one more thing that can be down.
How flag evaluation actually flows
A flag definition carries a targeting key, rules, and variations. The README's table of contents names the pieces: evaluation context, custom bucketing, variations, rollout, notifiers, export data. Rules target users based on the evaluation context you pass at call time, and bucketing decides which variation a given user lands in, with a custom bucketing option when the default does not fit.
On the Go side, the module retrieves the flag configuration through a retriever, then evaluates locally. The repository layout shows this split: retriever/ for the sources, exporter/ for evaluation data, notifier/ for change notifications, model/ for the flag types, and ffcontext/ plus ffuser/ for evaluation context. The top-level feature_flag.go, variation.go and tracking.go are the entry points a Go caller touches.
The relay proxy wraps the same engine in an HTTP server (cmd/relayproxy/) and exposes it to OpenFeature SDKs. Evaluation data can be exported to S3, Google Cloud Storage, Kafka, Kinesis, files and BigQuery, and flag changes can trigger webhooks or Slack messages. That export path is the part that makes experimentation measurable: without it, a flag change is an unlogged deploy. Note that the exporters pull in a large dependency tree (AWS SDK, Google Cloud clients, Sarama, pgx), which matters if you care about binary size or supply-chain surface.
Building and running the relay proxy
The README's getting-started flow has three steps: create a flag configuration file, create a relay proxy configuration file, then install the relay proxy. The repository also ships a Makefile target that builds the proxy binary into out/bin/relayproxy, and the Makefile comment notes that the binary is built with CGO_ENABLED=0.
make build-relayproxyThat target is defined in the repository's Makefile and produces out/bin/relayproxy. The Makefile also exposes a broader build target that compiles the modules, the relay proxy, the editor API, the JSON schema generator and the CLI into out/bin/.
make buildThe README says the relay proxy is the recommended way to get central flag management and multi-language support, and that the Go module is the alternative when your project is exclusively in Go. The module path is github.com/thomaspoignant/go-feature-flag, and go.mod declares go 1.26.6. On the client side, the README's OpenFeature path is: install the OpenFeature SDK for your language, initialize a client pointed at the proxy, then evaluate a flag by name with an evaluation context. The README does not give a Docker image name or a listening port in the excerpt, so check the website's relay proxy documentation for those rather than assuming values.
Where the file-based model bites back
Storing flags as files is the design choice that makes this project cheap to run, and it is also the source of most operational friction. Nothing in the file model gives you a staged rollout of the flag configuration itself. If you push a broken flags file to S3 or a ConfigMap, every service reading it gets the broken version on its next retrieval, and the README does not document rollback. You need your own versioning and your own way back.
There is no first-class approval workflow either. The repository contains a schema directory and a JSON schema generator (build-jsonschema-generator in the Makefile), so you can validate flag files in CI, and there is an examples/lint_flag_programmatically example. That is the substitute for a UI's guardrails: schema validation in a pipeline, not a review screen.
The relay proxy is a single point of failure for non-Go clients. If it is down and your SDK has no cached fallback, evaluation fails. The README does not describe the proxy's availability model in the excerpt, so treat resilience as something you configure and test yourself rather than something the project promises.
Finally, the Go library is the wrong tool for a polyglot backend that wants one flag source of truth. Importing the module in one service and using the proxy in another gives you two retrieval paths and two failure modes for the same flags.
How it differs from OpenFeature's own provider model and from hosted flag services
The comparison that matters most is with the OpenFeature ecosystem itself. OpenFeature standardizes the SDK interface; it does not ship a flag store. GO Feature Flag supplies the missing half: a flag format, retrievers, an evaluation engine and a proxy. If you already use an OpenFeature SDK, adopting GO Feature Flag means adding a provider and a place to keep flags, not rewriting call sites. That is the actual difference in approach, and it is why the README frames the project as part of the OpenFeature ecosystem rather than as a competing standard.
The second comparison is against hosted flag services. Those give you a web UI, targeting rules edited by non-engineers, audit history and SDKs maintained by the vendor. GO Feature Flag gives you files in your own storage and no vendor in the request path, but you build the editing experience. The related searches for a GO Feature Flag UI and editor point at exactly this gap; the repository's answer is a JSON schema and a lint example, not a product. If a product manager needs to toggle a flag without opening a pull request, this project will feel like a step backwards.
The third is against writing flags as environment variables or a config map. That works until you need per-user targeting, percentage rollouts or scheduled changes. GO Feature Flag's rollout strategies (experimentation, progressive, scheduled) are the reason to move off plain config, and the examples directory has one folder per strategy.
Maintenance, licensing and upgrade cost
The last push to the default branch was on 2026-08-18, and the most recent release is v1.55.2 from the same date, so the project is being maintained. The release cadence shows both a main version line and a separate cmd/wasm line (v0.2.4 on 2026-08-03), which means the WebAssembly build is versioned independently of the server and the Go module. If you depend on the wasm path, watch that version stream separately.
The licence is MIT, which is permissive and imposes no copyleft obligation on your own code. That is the whole of the licence implication this article can state; the LICENSE file is the authority and nothing here is legal advice. One practical note: the MIT licence covers the repository, but the exporters pull in AWS, Google Cloud, Azure and Confluent-adjacent client libraries under their own terms. If your organisation reviews transitive licences, the go.mod dependency list is the place to look, not the project licence alone.
Upgrade cost is mostly dependency churn. The go.mod pins a large set of cloud SDKs, and the Makefile carries a FIPS module version (read from .fips-version) plus a wasm stack-size guard. The Makefile comment explains that the wasm build raises the shadow stack from the wasm-ld default of 64KB to 1MB because recursive JSON decoding could overflow it and permanently poison the instance, and that verify-wasm-stack asserts the built binaries carry that size. That is a sign of active maintenance, and also a sign that the wasm target has sharp edges worth testing before you rely on it.
Editorial conclusion
Adopt GO Feature Flag if you want flag definitions in version-controlled files and you are willing to run the relay proxy so non-Go services can use the same flags. Do not adopt it if you need a hosted UI with approval workflows and audit trails, or if nobody on the team can own a config file and a proxy deployment. Verify first that your chosen retriever (file, HTTP, S3, Kubernetes, MongoDB, GitHub) matches where your configuration actually lives, and confirm the relay proxy's configuration keys against the website docs rather than the README, which only sketches the getting-started path.
Frequently asked questions
What does feature flag mean?
A feature flag is a switch in your code that decides which variation of a behaviour a given user or request receives. GO Feature Flag stores those switches in JSON, TOML or YAML files and evaluates them either in a Go process or through the relay proxy.
Should you remove feature flags?
The README does not discuss flag cleanup or lifecycle management, so it gives no guidance on removing flags. What it does document is notifiers (webhook and Slack) that fire when a flag changes, which is the closest thing to change tracking it offers.
How to use flags in Go?
The README offers two paths: import the module github.com/thomaspoignant/go-feature-flag and evaluate in-process, or run the relay proxy and use the OpenFeature Go SDK against it. The README recommends the relay proxy for central flag management and says the Go module is an option when your project is exclusively in Go.
Are feature flags good or bad?
The README does not make that argument; it links to a separate article explaining why feature flags can speed up iteration. The project's own position is that flags should be defined in files you control and evaluated through an open standard.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/thomaspoignant-go-feature-flag)