{"id":18377341,"url":"https://github.com/mwitkow/go-flagz","last_synced_at":"2025-12-15T00:04:20.799Z","repository":{"id":35131569,"uuid":"39337325","full_name":"mwitkow/go-flagz","owner":"mwitkow","description":"Dynamic flag management for Go.","archived":false,"fork":false,"pushed_at":"2021-04-12T11:42:48.000Z","size":398,"stargazers_count":206,"open_issues_count":6,"forks_count":24,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-12-06T00:03:16.746Z","etag":null,"topics":["configuration","dynamic-flags","etcd","flags","golang","kubernetes"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mwitkow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-19T14:50:49.000Z","updated_at":"2024-08-22T07:27:24.000Z","dependencies_parsed_at":"2022-08-17T21:25:38.097Z","dependency_job_id":null,"html_url":"https://github.com/mwitkow/go-flagz","commit_stats":null,"previous_names":["mwitkow-io/go-flagz"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwitkow%2Fgo-flagz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwitkow%2Fgo-flagz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwitkow%2Fgo-flagz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwitkow%2Fgo-flagz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mwitkow","download_url":"https://codeload.github.com/mwitkow/go-flagz/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230479864,"owners_count":18232630,"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":["configuration","dynamic-flags","etcd","flags","golang","kubernetes"],"created_at":"2024-11-06T00:27:48.073Z","updated_at":"2025-12-15T00:04:20.746Z","avatar_url":"https://github.com/mwitkow.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go FlagZ \n\n[![Travis Build](https://travis-ci.org/mwitkow/go-flagz.svg)](https://travis-ci.org/mwitkow/go-flagz)\n[![Go Report Card](https://goreportcard.com/badge/github.com/mwitkow/go-flagz)](http://goreportcard.com/report/mwitkow/go-flagz)\n[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/mwitkow/go-flagz)\n[![SourceGraph](https://sourcegraph.com/github.com/mwitkow/go-flagz/-/badge.svg)](https://sourcegraph.com/github.com/mwitkow/go-flagz/?badge)\n[![codecov](https://codecov.io/gh/mwitkow/go-flagz/branch/master/graph/badge.svg)](https://codecov.io/gh/mwitkow/go-flagz)\n[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n\nDynamic, thread-safe `flag` variables that can be modified at runtime through [etcd](https://github.com/coreos/etcd)\nor [Kubernetes](http://kubernetes.io).\n\nFor a similar project for JVM languages (Java, scala) see [java-flagz](https://github.com/mwitkow/java-flagz)\n \n## This sounds crazy. Why?\n\nFile-based or command-line configuration can only be changed when a service restarts. Dynamic flags provide\nflexibility in normal operations and emergencies. Two examples:\n \n * A new feature launches that you want to A/B test. You want to gradually enable it for a certain fraction of user\n requests (1%, 5%, 20%, 50%, 100%) without the need to restart servers.\n * Your service is getting overloaded and you want to disable certain costly features. You can't afford \n restarting because you'd lose important capacity.\n \nAll of this can be done simultaneously across a whole shard of your services.\n\n## Features\n\n * compatible with popular `flag` replacement [`spf13/pflag`](https://github.com/spf13/pflag) (e.g. ones using [`spf13/cobra`](https://github.com/spf13/cobra))\n * dynamic `flag` that are thread-safe and efficient:\n   - `DynInt64`\n   - `DynFloat64`\n   - `DynString`\n   - `DynDuration`\n   - `DynStringSlice`\n   - `DynJSON` - a `flag` that takes an arbitrary JSON struct\n   - `DynProto3` - a `flag` that takes a `proto3` struct in JSONpb or binary form\n * `validator` functions for each `flag`, allows the user to provide checks for newly set values\n * `notifier` functions allow user code to be subscribed to `flag` changes\n * Kubernetes `ConfigMap` watcher, see [configmap/README.md](configmap/README.md).\n * `etcd` based watcher that syncs values from a distributed Key-Value store into the program's memory\n * Prometheus metric for checksums of the current flag configuration\n * a `/debug/flagz` HandlerFunc endpoint that allows for easy inspection of the service's runtime configuration\n\nHere's a teaser of the debug endpoint:\n\n![Status Endpoint](https://raw.githubusercontent.com/mwitkow/go-flagz/screenshots/screenshot_endpoint.png)\n\n## Examples\n\nDeclare a single `pflag.FlagSet` in some public package (e.g. `common.SharedFlagSet`) that you'll use throughout your server.\n\n\n### Dynamic JSON flag with a validator and notifier\n\n```go\nvar (\n  limitsConfigFlag = flagz.DynJSON(\n    common.SharedFlagSet, \n    \"rate_limiting_config\", \n    \u0026rateLimitConfig{ DefaultRate: 10, Policy: \"allow\"},\n    \"Config for service's rate limit\",\n  ).WithValidator(rateLimitConfigValidator).WithNotifier(onRateLimitChange)\n)\n```\n\nThis declares a JSON flag of type `rateLimitConfig` with a default value. Whenever the config changes (statically or dynamically) the `rateLimitConfigValidator` will be called. If it returns no errors, the flag will be updated and `onRateLimitChange` will be called with both old and new, allowing the rate-limit mechanism to re-tune.\n\n## Dynamic feature flags\n\n```go\nvar (\n  featuresFlag = flagz.DynStringSlice(common.SharedFlagSet, \"enabled_features\", []string{\"fast_index\"}, \"list of enabled feature markers\")\n)\n...\nfunc MyHandler(resp http.ResponseWriter, req *http.Request) {\n   ...\n   if existsInStringSlice(\"fast_index\", featuresFlag.Get()) {\n     doFastIndex(req)\n   }\n   ...\n}\n```\n\nAll access to `featuresFlag`, which is a `[]string` flag, is synchronised across go-routines using `atomic` pointer swaps. \n\n## Watching for changes from etcd\n\n```go\n// First parse the flags from the command line, as normal.\ncommon.SharedFlagSet.Parse(os.Args[1:])\nw, err := watcher.New(common.SharedFlagSet, etcdClient, \"/my_service/flagz\", logger)\nif err != nil {\n  logger.Fatalf(\"failed setting up %v\", err)\n}\n// Read flagz from etcd and update their values in common.SharedFlagSet\nif err := w.Initialize(); err != nil {\n\tlog.Fatalf(\"failed setting up %v\", err)\n}\n// Start listening of dynamic flags from etcd.\nw.Start()\n```\n\nThe `watcher`'s go-routine will watch for `etcd` value changes and synchronise them with values in memory. In case a value fails parsing or the user-specified `validator`, the key in `etcd` will be atomically rolled back.\n\n## More examples:\n\n * [simple http server](examples/server)\n * [printing CLI command](examples/cli)\n\n# Status\n\nThis code is *production* quality. It's been running happily in production at Improbable for a few months.\n\nFeatures planned:\n \n  * [x] - [#11](https://github.com/mwitkow/go-flagz/issues/11) monitoring of `FlagSet` checksus using a Prometheus handler\n  * [ ] - [#12](https://github.com/mwitkow/go-flagz/issues/12) support for standard `flag` (requires changes in `spf13/pflag` interfaces)\n\n### License\n\n`go-flagz` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwitkow%2Fgo-flagz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmwitkow%2Fgo-flagz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwitkow%2Fgo-flagz/lists"}