Feature Flags
Runtime feature toggling without deployments. Define flags with defaults, check them anywhere, and toggle via API or admin panel.
Setup
import "github.com/CodeSyncr/nimbus/flags"
app.Use(flags.NewPlugin())
Defining Flags
// Boolean flag with default
flags.Define("dark_mode", false)
// Integer flag
flags.Define("max_upload_mb", 10)
// String flag
flags.Define("maintenance_message", "")
// Boolean for beta features
flags.Define("beta_features", false)
Checking Flags
// Boolean check
if flags.Enabled("dark_mode") {
// Show dark theme
}
// Get typed values
maxUpload := flags.Get[int]("max_upload_mb")
message := flags.Get[string]("maintenance_message")
// Toggle at runtime (via API or admin panel)
flags.Set("dark_mode", true)
flags.Set("max_upload_mb", 25)
Real-Life Examples
A/B Testing
func (ctrl *ProductController) Show(c *http.Context) error {
product := getProduct(c.Param("id"))
if flags.Enabled("new_product_page") {
return c.View("products/show_v2", product)
}
return c.View("products/show", product)
}
Gradual Rollout
func (ctrl *CheckoutController) Store(c *http.Context) error {
if flags.Enabled("new_payment_flow") {
return processPaymentV2(c)
}
return processPayment(c)
}
Maintenance Mode
func MaintenanceMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if flags.Enabled("maintenance_mode") {
msg := flags.Get[string]("maintenance_message")
http.Error(w, msg, http.StatusServiceUnavailable)
return
}
next.ServeHTTP(w, r)
})
}
Best Practices
- Always define flags with sensible defaults
- Use descriptive names:
new_checkout_flownotflag1 - Remove flags after a feature is fully rolled out
- Use flags for rollouts and experiments, not permanent configuration
- Combine with
cacheto store flag state in Redis for multi-instance sync