Feature Flags & OpenFeature
Diverge provides first-class support for feature flags and remote configuration across ephemeral preview environments using the vendor-neutral OpenFeature standard.
Rather than inventing a proprietary feature flag API, Diverge pairs a runtime OpenFeature Hook with a pluggable control-plane provider interface, allowing your existing application code and feature flag systems to work seamlessly without vendor lock-in.
Architectural Model
Section titled “Architectural Model”Diverge’s feature management operates across two decoupled planes:
┌─────────────────────────────────────────────────────────────┐│ Control Plane (Diverge Controller) ││ ││ .diverge.yaml ──► FeatureProvider.Provision() ││ │ ││ ▼ ││ ┌───────────────────────────────┐ ││ │ diverge-features-<env> (CM) │ ││ │ └── flags.json (flagd) │ ││ │ └── overrides.json │ ││ └───────────────────────────────┘ │└──────────────────────────────┬──────────────────────────────┘ │ Mounts into Pod ▼┌─────────────────────────────────────────────────────────────┐│ Data Plane (Application Pods) ││ ││ HTTP Request (x-diverge-env: pr-42) ││ │ ││ ▼ ││ diverge/sdk HTTP Middleware ──► context.Context ││ │ ││ ▼ ││ OpenFeature Client ──────────► DivergeHook.Before() ││ │ ││ ▼ Injects: ││ diverge.environment = "pr-42" ││ diverge.is_preview = true ││ │ ││ ▼ ││ OpenFeature Provider (flagd / Flipt / Flagsmith / Unleash) │└─────────────────────────────────────────────────────────────┘- Control Plane (
FeatureProvider): When an environment is created, the Diverge controller invokes the configuredFeatureProviderto provision ephemeral feature rules or ConfigMaps scoped to that environment. - Data Plane (
DivergeHook): Application code makes standard OpenFeature evaluation calls. TheDivergeHooktransparently extracts the preview environment from the request context and enriches OpenFeature’sEvaluationContextwithdiverge.environmentanddiverge.is_preview.
Configuring .diverge.yaml
Section titled “Configuring .diverge.yaml”Feature overrides can be declared globally, overridden per environment type, or injected on-demand via pull request labels:
version: "1"
defaults: features: provider: configmap overrides: checkout_v2: "false" billing_redesign: "false" rate_limit_per_minute: "100"
environments: preview: features: overrides: checkout_v2: "true" # Turn on new checkout in preview environments
label_overrides: flag/fast-checkout: features: overrides: checkout_v2: "true" fast_lane: "enabled"Provider Options
Section titled “Provider Options”| Provider | Description | Infrastructure Required |
|---|---|---|
configmap (default) |
Generates a Kubernetes ConfigMap formatted for flagd / in-process JSON evaluation. | Zero — entirely Kubernetes-native. |
noop / none |
Disables feature flag provisioning. | None. |
flipt |
Provisions an ephemeral namespace (diverge-<envName>) and targeting rules in Flipt. |
Flipt server. |
flagsmith |
Provisions an ephemeral identity (diverge-[<ns>-]<env>-<hash8>) and traits in Flagsmith. |
Flagsmith server or cloud. |
unleash |
Provisions context-constrained flexibleRollout strategies (diverge.environment IN [<env>]) and strategy-level variants in Unleash. |
Unleash server or Enterprise. |
The Zero-Infrastructure ConfigMap Provider
Section titled “The Zero-Infrastructure ConfigMap Provider”By default, Diverge uses the configmap provider. When an environment pr-42 is provisioned:
- Diverge generates a ConfigMap named
diverge-features-pr-42in the environment’s target namespace. - The ConfigMap contains a flagd-compliant
flags.jsonfile, along with raw key-value pairs:
{ "flags": { "checkout_v2": { "state": "ENABLED", "variants": { "on": true, "off": false }, "defaultVariant": "on" } }}- The ConfigMap is linked to the
Environmentvia Kubernetes Owner References, ensuring automatic garbage collection when the preview environment is torn down.
Remote Enterprise Providers (flipt, flagsmith, unleash)
Section titled “Remote Enterprise Providers (flipt, flagsmith, unleash)”All remote providers support 4-tier credential resolution:
features.connection_refSecret in theEnvironment’s namespacefeatures.connection_refSecret indiverge-system- Default Secret names (
<provider>-connectionor<provider>-credentials) inenv.Namespaceordiverge-system - Controller environment variables (
DIVERGE_<PROVIDER>_*)
Unleash (features.provider: unleash)
Section titled “Unleash (features.provider: unleash)”When provider: unleash is configured, Diverge ensures each overridden feature toggle exists and is enabled in your target Unleash project/environment, and upserts a preview-scoped flexibleRollout strategy (diverge-[<ns>-]<env>-<hash8>, sortOrder: 0) constrained to diverge.environment IN [<envName>]. Boolean "false" overrides also attach a diverge.environment NOT_IN [<envName>] exclusion constraint to other strategies on that feature so broader strategies cannot enable the flag in the preview environment. String/variant overrides attach a strategy-level variant (weight: 1000). When overrides are removed or the environment is torn down, all preview strategies and exclusion constraints for the environment are deleted automatically.
apiVersion: v1kind: Secretmetadata: name: unleash-credentials namespace: diverge-systemtype: OpaquestringData: url: "https://unleash.internal.example.com" adminToken: "*:*.unleash_admin_token..." clientToken: "default:development.unleash_client_token..." project: "default" environment: "development"Injected workload environment variables: UNLEASH_URL, UNLEASH_API_TOKEN (populated from clientToken; adminToken is never sent to preview workloads), UNLEASH_PROJECT, UNLEASH_ENVIRONMENT, UNLEASH_STRATEGY_TITLE, OPENFEATURE_UNLEASH_URL, OPENFEATURE_UNLEASH_API_TOKEN, and OPENFEATURE_TARGET_KEY.
Application Integration with OpenFeature
Section titled “Application Integration with OpenFeature”In your application, register Diverge’s DivergeHook on your OpenFeature client.
Go Example
Section titled “Go Example”package main
import ( "context" "fmt" "net/http"
of "github.com/open-feature/go-sdk/openfeature" divergeof "github.com/divergedev/diverge/pkg/sdk/openfeature" divergehttp "github.com/divergedev/diverge/pkg/sdk/http")
func main() { // 1. Create your OpenFeature client and register the DivergeHook client := of.NewClient("checkout-service") client.AddHooks(divergeof.NewDivergeHook())
// 2. Wrap your HTTP handlers with Diverge context propagation middleware mux := http.NewServeMux() mux.HandleFunc("/checkout", func(w http.ResponseWriter, r *http.Request) { ctx := r.Context()
// 3. Evaluate flags using standard OpenFeature APIs! // DivergeHook automatically injects diverge.environment and diverge.is_preview isV2Enabled, _ := client.BooleanValue(ctx, "checkout_v2", false, of.EvaluationContext{})
if isV2Enabled { fmt.Fprintln(w, "Rendering Checkout V2 (Preview)") } else { fmt.Fprintln(w, "Rendering Checkout Baseline") } })
handler := divergehttp.Middleware()(mux) http.ListenAndServe(":8080", handler)}When a request arrives with x-diverge-env: pr-42, the OpenFeature provider evaluates targeting rules matching diverge.environment == "pr-42".
Provider Discovery CLI
Section titled “Provider Discovery CLI”Inspect available providers registered on your cluster or CLI with diverge providers list:
$ diverge providers list--- feature ---NAME DESCRIPTIONconfigmap Kubernetes ConfigMap feature flag provider (flagd & OpenFeature file provider)flagsmith Flagsmith remote feature flag & remote config provider (ephemeral identity & trait overrides)flipt Flipt remote feature flag provider (ephemeral namespaces & segment overrides)none None feature flag provider (disables feature provisioning)noop No-op feature flag provider (disables feature provisioning)unleash Unleash enterprise feature flag provider (context-constrained activation strategies & variants)