Skip to Content
DocsFeature Flag User Guide

Feature Flag User Guide

A practical guide to every flag type and targeting scenario supported by GoGreen Flags, with dashboard configuration steps and SDK code examples.

Core Concepts

ConceptDescription
FlagA named toggle with one or more variations. Identified by a unique key (e.g. new-checkout).
VariationA possible value a flag can return. Boolean flags have two (true/false); other types can have many.
RuleA targeting condition. Rules contain clauses (AND logic) and an optional rollout strategy. Evaluated top-to-bottom by priority.
ClauseA single condition: attribute operator value(s). Multiple clauses in a rule are ANDed together.
SegmentA reusable group of users, defined by rules or an explicit list. Referenced via the segment_match operator.
EnvironmentAn isolated evaluation context (e.g. Development, Staging, Production). Each has its own rules, SDK key, and rollout schedule.
Evaluation ContextThe user or entity being evaluated. Has a key (unique ID) and custom attributes (e.g. email, country, plan).
Default ValueThe fallthrough value returned when no rules match and the flag is enabled.
Off VariationThe value returned when the flag is disabled.

Evaluation Order

1. Is the flag enabled? No → return Off Variation (reason: OFF) Yes → continue 2. Are all prerequisites met? No → return Off Variation (reason: PREREQUISITE_FAILED) Yes → continue 3. Evaluate rules in priority order (top to bottom): Rule matches → apply rollout strategy or return variation (reason: RULE_MATCH) 4. No rules matched → return Default value (reason: DEFAULT)

Getting Started

Install the SDK

Go:

go get github.com/gogreen/sdk-go

TypeScript / Node.js:

npm install @gogreenflags/sdk

Initialize the Client

Go:

package main import ( "log" "time" gogreen "github.com/gogreen/sdk-go" shared "github.com/gogreen/shared-data" ) func main() { client, err := gogreen.NewClient(gogreen.Config{ SDKKey: "sdk_your_key_here", EnvID: "env_your_env_id", APIBaseURL: "https://app.gogreenflags.com", StreamURL: "https://app.gogreenflags.com", EventsURL: "https://app.gogreenflags.com", EnableStreaming: true, PollInterval: 30 * time.Second, }) if err != nil { log.Fatalf("Failed to create client: %v", err) } defer client.Close() if err := client.WaitForInitialization(10 * time.Second); err != nil { log.Printf("Warning: SDK not yet initialized: %v", err) } user := shared.EvaluationContext{ Key: "user-42", Custom: map[string]interface{}{ "email": "alice@example.com", "country": "US", "plan": "pro", }, } enabled := client.BoolVariation("new-checkout", user, false) log.Printf("new-checkout = %v", enabled) }

TypeScript (CommonJS — for ESM projects see SDK Reference):

import { GoGreenClient } from '@gogreenflags/sdk'; const client = new GoGreenClient({ sdkKey: 'sdk_your_key_here', environmentId: 'env_your_env_id', apiBaseUrl: 'https://app.gogreenflags.com', streamUrl: 'https://app.gogreenflags.com', eventsUrl: 'https://app.gogreenflags.com', enableStreaming: true, defaultContext: { key: 'user-42', custom: { email: 'alice@example.com', country: 'US', plan: 'pro', }, }, }); await client.waitForInitialization(); const enabled = await client.boolVariation('new-checkout', false); console.log('new-checkout =', enabled);

Where to Find Your SDK Key

  1. Open the GoGreen Flags dashboard
  2. Go to Project Settings → Environments
  3. Expand the target environment (e.g. “Production”)
  4. Copy the SDK Key (client-side) or Server Key (server-side)

Flag Types

Boolean Flags

The most common type. Returns true or false.

When to use: Feature toggles, kill switches, opt-in features, two-variant A/B tests.

Dashboard setup:

  1. Click Create Flag
  2. Set Key: new-checkout
  3. Set Type: Boolean
  4. Two variations are created automatically: true and false

SDK usage:

// Go — synchronous, returns from local config enabled := client.BoolVariation("new-checkout", user, false) if enabled { showNewCheckout() } else { showOldCheckout() }
// TypeScript — async const enabled = await client.boolVariation('new-checkout', false);

With evaluation detail:

val, detail := client.BoolVariationDetail("new-checkout", user, false) log.Printf("Value: %v, Reason: %s, Rule: %v", val, detail.Reason.Kind, detail.RuleIndex) // Value: true, Reason: RULE_MATCH, Rule: 0
const detail = await client.boolVariationDetail('new-checkout', false); console.log(`Value: ${detail.value}, Reason: ${detail.reason}`);

String Flags

Returns a string value. Useful for selecting between named variants.

When to use: Theme selection, algorithm variants, banner copy, locale-specific messages.

Dashboard setup:

  1. Create flag with Type: String
  2. Add variations: control = "classic", treatment-a = "modern", treatment-b = "minimal"
  3. Set the Default to "classic"
theme := client.StringVariation("checkout-theme", user, "classic") switch theme { case "modern": renderModernCheckout() case "minimal": renderMinimalCheckout() default: renderClassicCheckout() }
const theme = await client.stringVariation('checkout-theme', 'classic');

Number Flags

Returns a numeric value (float64). Useful for tuning parameters without redeploying.

When to use: Rate limits, timeout values, retry counts, cache TTLs, discount percentages.

Dashboard setup:

  1. Create flag with Type: Number
  2. Add variations: low = 100, medium = 500, high = 2000
rateLimit := client.NumberVariation("api-rate-limit", user, 100) limiter.SetLimit(rateLimit)
const rateLimit = await client.numberVariation('api-rate-limit', 100);

JSON Flags

Returns a structured JSON object. The most flexible type.

When to use: UI layout configs, experiment parameters, feature bundles, dynamic form schemas.

Dashboard setup:

  1. Create flag with Type: JSON
  2. Add variations with JSON values, for example:
    • compact: {"layout": "single-column", "showSidebar": false, "maxItems": 10}
    • full: {"layout": "two-column", "showSidebar": true, "maxItems": 50}
config := client.JSONVariation("dashboard-layout", user, defaultCfg) if cfg, ok := config.(map[string]interface{}); ok { layout := cfg["layout"].(string) renderDashboard(layout) }
const config = await client.jsonVariation('dashboard-layout', { layout: 'single-column', showSidebar: false, maxItems: 10, });

Targeting Scenarios

Kill Switch (Global On/Off)

The flag is either on or off for everyone. No targeting rules needed.

When to use: Emergency shutoff, maintenance mode, global feature launch.

Dashboard: Toggle the flag’s enabled switch. Set the Off Variation to false.

if client.BoolVariation("maintenance-mode", user, false) { http.Error(w, "System under maintenance", http.StatusServiceUnavailable) return }
if (await client.boolVariation('maintenance-mode', false)) { return res.status(503).json({ message: 'System under maintenance' }); }

User Targeting (Individual Users)

Target specific users by their unique key.

When to use: Internal dogfooding, individual opt-in, VIP access, debugging.

Dashboard:

  1. Add a Rule → Clause: key eq user-42, user-99
  2. Serve: true
alice := shared.EvaluationContext{Key: "user-42"} // matches → true bob := shared.EvaluationContext{Key: "user-999"} // no match → default

Attribute-Based Targeting

Target users based on custom attributes like email, country, or plan.

When to use: Geo-targeting, plan-based features, internal users, email domain filtering.

Dashboard — Example: Pro plan users in the US:

  1. Add a rule with two clauses (AND):
    • plan eq pro
    • country eq US
  2. Serve: true

Dashboard — Example: Internal users by email domain:

  1. Rule: email ends_with @company.com
  2. Serve: true
user := shared.EvaluationContext{ Key: "user-42", Custom: map[string]interface{}{ "email": "alice@company.com", "country": "US", "plan": "pro", }, } enabled := client.BoolVariation("us-pro-feature", user, false) // true
const enabled = await client.boolVariation('us-pro-feature', false, { key: 'user-42', custom: { email: 'alice@company.com', country: 'US', plan: 'pro' }, });

Negation: Any clause can be negated by toggling the Negate option, which inverts the result. For example, country eq US with negate means “country is NOT US”.

Segment Targeting

Target pre-defined groups of users using reusable segments.

When to use: Beta testers, enterprise customers, QA teams, geographic regions.

Dashboard:

  1. Create a segment (see Segments section below)
  2. In the flag rule, add clause: segment_match = beta-testers
  3. Serve: the desired variation
// Segment membership is evaluated locally from cached config. // No extra API call is needed. user := shared.EvaluationContext{ Key: "user-42", Custom: map[string]interface{}{"plan": "enterprise"}, } enabled := client.BoolVariation("beta-feature", user, false)

Percentage Rollout

Gradually release a feature to a percentage of users. The assignment is deterministic — the same user always gets the same variation (based on MurmurHash3 of flagKey.userKey.salt).

When to use: Gradual feature release, A/B testing, canary deployments, risk mitigation.

Dashboard:

  1. Open flag → Rules → Add rule
  2. Under Serve, select Percentage Rollout
  3. Set distribution: true 10%, false 90%

The hash algorithm provides 0.01% precision (10,000 buckets).

// ~10% get true, ~90% get false. Same user always gets the same result. enabled := client.BoolVariation("new-algorithm", user, false)

Multi-variation percentage rollout (string flag):

control: 50% treatment-a: 30% treatment-b: 20%
variant := client.StringVariation("checkout-experiment", user, "control")

Gradual Rollout Schedule

Automatically ramp a percentage rollout over time without manual intervention.

When to use: Multi-day feature launches, time-gated releases, automated canary progression.

Dashboard:

  1. Open flag → Gradual rollout schedule card
  2. Click Create gradual rollout schedule
  3. Select the Target variation (e.g. the true variation)
  4. Define steps:
StepPercentageDelay until next
11%60 minutes
210%120 minutes
350%240 minutes
4100%0 minutes
  1. Click Start gradual rollout

The system automatically advances to the next step after each delay. The dashboard shows current step, status (active, paused, completed), and next advance time.

Controls:

  • Rollback: Revert to the previous step if issues are detected
  • Delete schedule: Stop automatic advancement

No SDK changes needed — the rollout schedule updates the underlying percentage on the server. The SDK receives updated config via streaming/polling.

// At t=0: ~1% of users get true // At t=60m: ~10% get true // At t=180m: ~50% get true // At t=420m: 100% get true enabled := client.BoolVariation("new-feature", user, false)

Multi-Variate (A/B/n Testing)

Test more than two variants simultaneously using string, number, or JSON flags.

When to use: Testing multiple UI designs, pricing strategies, algorithm variants.

Dashboard:

  1. Create a string flag pricing-page with 4 variations: original, simplified, comparison-table, interactive-calculator
  2. Add a rule with Percentage Rollout: 25% each
  3. Optionally create an Experiment linked to this flag to track metrics
variant := client.StringVariation("pricing-page", user, "original") switch variant { case "simplified": renderSimplifiedPricing() case "comparison-table": renderComparisonTable() case "interactive-calculator": renderInteractiveCalculator() default: renderOriginalPricing() } // Track conversion client.Track("pricing_page_signup", user, map[string]any{ "variant": variant, "revenue": 29.99, })
const variant = await client.stringVariation('pricing-page', 'original'); client.track('pricing_page_signup', { variant, revenue: 29.99 });

Prerequisites (Flag Dependencies)

Make a flag depend on another flag’s value. The dependent flag returns its off variation unless all prerequisites are met.

When to use: Feature chains (B requires A), tiered rollouts, coordinated launches.

Dashboard:

  1. Open the dependent flag (e.g. advanced-analytics)
  2. Add a Prerequisite: Flag = basic-analytics, Required variation = true
  3. Save

Now advanced-analytics only evaluates if basic-analytics returns true for the same user.

val, detail := client.BoolVariationDetail("advanced-analytics", user, false) if detail.Reason.Kind == "PREREQUISITE_FAILED" { log.Printf("Blocked by prerequisite: %s", detail.Reason.PrerequisiteKey) }

Prerequisites are checked recursively (max 10 levels). Circular dependencies are rejected at save time.

Canary Release

Release to a small percentage first, monitor, then increase.

When to use: Risky deployments, infrastructure changes, database migrations behind a flag.

Manual canary:

  1. Create boolean flag → percentage rollout: 1% true, 99% false
  2. Monitor metrics and errors
  3. Manually increase: 1% → 5% → 25% → 100%

Automated canary (gradual rollout):

  1. Use a Gradual rollout schedule: 1% (30m) → 5% (60m) → 25% (120m) → 100%
  2. If errors spike, click Rollback to previous step
if client.BoolVariation("new-payment-processor", user, false) { result, err := newProcessor.Charge(amount) if err != nil { metrics.IncrCounter("payment.new_processor.errors", 1) } } else { result, err := oldProcessor.Charge(amount) }

Ring-Based Deployment

Use segments to define deployment rings: internal → beta → early adopters → everyone.

When to use: Enterprise rollouts, platform migrations, structured validation at each ring.

Dashboard:

  1. Create segments:
    • ring-0-internal: list-based (employee user IDs)
    • ring-1-beta: list-based (beta program members)
    • ring-2-early-adopters: rule-based (plan eq enterprise)
  2. Add rules in priority order:
PriorityRuleServe
1segment_match = ring-0-internaltrue
2segment_match = ring-1-betatrue
3segment_match = ring-2-early-adopterstrue
  1. Default: false
  2. Enable each ring progressively by toggling the rule’s enabled state

Time-Based Targeting

Target users based on timestamps using the before and after operators (RFC 3339 format).

When to use: Scheduled launches, time-limited promotions, sunset dates.

Dashboard:

  1. Rule: launch_time after 2026-04-01T00:00:00Z
  2. Serve: true
user := shared.EvaluationContext{ Key: "user-42", Custom: map[string]interface{}{ "launch_time": time.Now().Format(time.RFC3339), }, } enabled := client.BoolVariation("spring-sale", user, false)

Pass the current time as a custom attribute so the evaluation engine can compare against the rule.

Semver-Based Targeting

Target users based on their app or SDK version using semantic version operators.

When to use: Feature gating by client version, forcing minimum versions, deprecating old clients.

Dashboard — Enable for apps >= v2.5.0:

  1. Rule: app_version semver_gte 2.5.0
  2. Serve: true
user := shared.EvaluationContext{ Key: "user-42", Custom: map[string]interface{}{"app_version": "2.7.1"}, } enabled := client.BoolVariation("new-api-v2", user, false) // true

The v prefix is stripped automatically — both v2.5.0 and 2.5.0 work.


Segments

Segments are reusable groups of users referenced across multiple flags.

Rule-Based Segments

Membership determined dynamically by evaluating clauses against user attributes.

When to use: Groups defined by characteristics (enterprise customers, European users, users on a specific plan).

Dashboard:

  1. Segments → Create Segment
  2. Key: enterprise-customers, Type: Rule-based
  3. Add constraints: plan eq enterprise
  4. Save

Preview membership: In segment detail → Targeting Rules tab → enter user keys in Preview matched users → click Preview. Shows a table of which keys match.

List-Based Segments

Membership is an explicit, fixed list of user keys.

When to use: Beta program members, specific accounts, employee IDs, test accounts.

Dashboard:

  1. Create segment with Type: List-based
  2. In Included Members tab:
    • Manual: Type a user key and click Add
    • CSV upload: One key per line
    • JSON upload: JSON array of keys
  3. Supports up to 1M entries via file upload (stream-processed server-side)

Environments

Environments isolate flag configuration. Each environment has its own targeting rules, rollout schedules, SDK key, and server key.

Typical setup:

EnvironmentPurpose
DevelopmentLocal dev, all flags on
StagingPre-production testing
ProductionLive users, protected

SDK per environment:

// Production client, _ := gogreen.NewClient(gogreen.Config{ SDKKey: "sdk_prod_abc123", EnvID: "env_production_id", }) // Staging client, _ := gogreen.NewClient(gogreen.Config{ SDKKey: "sdk_stg_xyz789", EnvID: "env_staging_id", })

Key rotation: Use the Rotate keys button in Environment Settings. Update your SDK configuration with the new key and redeploy.


Lifecycle Types

Organize flags by purpose to keep your flag inventory healthy.

TypeDescriptionStaleness
releaseStandard feature release. Remove after full rollout.Flagged as stale after extended time at 100%
experimentA/B test flag. Remove after experiment concludes.Stale when experiment is stopped
opsOperational toggle (kill switch, circuit breaker).May be long-lived
permissionAccess control toggle (feature tier, RBAC).Long-lived by design
permanentExplicitly marked as never stale.Never flagged

The dashboard highlights stale flags so you can clean them up.


Experimentation

Link a flag to an experiment to measure the impact of different variations.

Dashboard:

  1. Create a multi-variation flag
  2. Experiments → Create Experiment
  3. Configure: name, feature flag, baseline variation, metrics (event type + aggregation)
  4. Click Start Experiment

Track events:

client.Track("pricing_page_signup", user, map[string]any{"revenue": 29.99})
client.track('pricing_page_signup', { revenue: 29.99 });

The experimentation service computes results (winner, confidence, p-value) displayed in the dashboard.


Production Safeguards

Environment Protection

Require approval before changes go live in production.

Dashboard: Project Settings → Environments → Protection:

  • Require approval: On
  • Minimum reviewers: 1+
  • Allow flag owner to approve: On/Off
  • Auto-expire hours: Optional

Diff Modal

When saving changes in a production environment, a diff modal shows JSON before/after and requires a mandatory comment.

Audit Log

All changes logged in the Audit Log with filtering by date, actor, action, and resource. Export as CSV for compliance.


OpenFeature Integration

GoGreen Flags provides an OpenFeature  provider for vendor-neutral flag evaluation.

Go:

import ( gogreen "github.com/gogreen/sdk-go" "github.com/open-feature/go-sdk/openfeature" ) ggClient, _ := gogreen.NewClient(gogreen.Config{ SDKKey: "sdk_your_key", EnvID: "env_your_id", APIBaseURL: "https://app.gogreenflags.com", }) defer ggClient.Close() provider := gogreen.NewGoGreenProvider(ggClient) openfeature.SetProvider(provider) ofClient := openfeature.NewClient("my-app") evalCtx := openfeature.NewEvaluationContext("user-42", map[string]interface{}{ "email": "alice@example.com", }) enabled, _ := ofClient.BooleanValue(ctx, "new-checkout", false, evalCtx)

TypeScript:

import { GoGreenClient } from '@gogreenflags/sdk'; import { GoGreenProvider } from '@gogreenflags/sdk/provider'; import { OpenFeature } from '@openfeature/server-sdk'; const ggClient = new GoGreenClient({ sdkKey: 'sdk_your_key', environmentId: 'env_id', defaultContext: { key: 'anonymous' } }); await OpenFeature.setProviderAndWait(new GoGreenProvider(ggClient)); const ofClient = OpenFeature.getClient('my-app'); const enabled = await ofClient.getBooleanValue('new-checkout', false, { targetingKey: 'user-42' });

React Integration

The TypeScript SDK includes a React provider and useFeatureFlag hook.

import { GoGreenProvider, useFeatureFlag } from '@gogreenflags/sdk/react'; function App() { return ( <GoGreenProvider config={{ sdkKey: 'sdk_your_client_key', environmentId: 'env_your_id', apiBaseUrl: 'https://app.gogreenflags.com', enableStreaming: true, defaultContext: { key: currentUser.id, custom: { email: currentUser.email } }, }}> <MyApp /> </GoGreenProvider> ); } function CheckoutPage() { const { value: useNewCheckout, loading } = useFeatureFlag('new-checkout', false); if (loading) return <Spinner />; return useNewCheckout ? <NewCheckout /> : <ClassicCheckout />; }

Testing with Feature Flags

Test Client

Both SDKs provide a test client that returns predetermined values without network calls.

Go:

client := gogreen.NewTestClient(map[string]interface{}{ "new-checkout": true, "checkout-theme": "modern", "rate-limit": 500.0, }) defer client.Close() val := client.BoolVariation("new-checkout", user, false) // true

TypeScript:

const client = GoGreenClient.testClient({ 'new-checkout': true, 'checkout-theme': 'modern', }); const enabled = await client.boolVariation('new-checkout', false); // true

Bootstrap & Offline Mode

Pre-load flag values for integration tests:

client, _ := gogreen.NewClient(gogreen.Config{ SDKKey: "test-key", EnvID: "test-env", Offline: true, BootstrapConfig: &shared.EnvironmentConfig{ Flags: map[string]shared.FlagConfig{ "new-checkout": {Key: "new-checkout", Type: "boolean", Enabled: true, Default: true}, }, }, })

Toggle offline mode at runtime:

client.EnterOfflineMode() // Freeze flag values client.ExitOfflineMode() // Resume streaming/polling

Operator Reference

String Operators

OperatorDescriptionExample
eqEquals any value in listcountry eq US, UK
neqNot equal to any valueplan neq free
inIs in list (alias for eq)role in admin, editor
containsContains substringemail contains @company
does_not_containDoes not containemail does_not_contain test
starts_withStarts with prefixemail starts_with admin@
ends_withEnds with suffixemail ends_with @company.com
matches_regexMatches regexpath matches_regex ^/api/v[0-9]+

Numeric Operators

OperatorDescriptionExample
gtGreater thanage gt 18
gteGreater than or equalscore gte 100
ltLess thanerror_rate lt 5
lteLess than or equallatency_ms lte 200

Semantic Version Operators

OperatorDescriptionExample
semver_eqVersion equalsapp_version semver_eq 2.0.0
semver_gtGreater thanapp_version semver_gt 1.9.0
semver_gteGreater than or equalsdk_version semver_gte 3.0.0
semver_ltLess thanapp_version semver_lt 2.0.0
semver_lteLess than or equalapp_version semver_lte 1.5.0

Date/Time Operators

OperatorDescriptionExample
beforeTimestamp before valuecreated_at before 2026-01-01T00:00:00Z
afterTimestamp after valuelaunch_time after 2026-04-01T00:00:00Z

Values must be RFC 3339 format.

Segment Operator

OperatorDescriptionExample
segment_matchUser is in the named segmentsegment_match beta-testers

Quick Reference Cheat Sheet

ScenarioFlag TypeKey Setup
Kill switchBooleanToggle flag on/off, no rules
Feature releaseBooleanPercentage rollout 0% → 100%
Canary releaseBooleanGradual rollout schedule (1% → 5% → 25% → 100%)
A/B test (2 variants)Boolean50/50 percentage rollout + experiment
A/B/n test (3+ variants)StringMulti-variation percentage rollout + experiment
User opt-inBooleanRule: key eq specific user IDs
Beta programBooleanSegment (list-based) + segment_match rule
Geo-targetingBooleanRule: country eq target countries
Plan-gated featureBooleanRule: plan eq pro, enterprise
Internal dogfoodingBooleanRule: email ends_with @company.com
Dynamic configJSONJSON flag with structured config object
Tunable parameterNumberNumber flag with named variations
Version gateBooleanRule: app_version semver_gte minimum version
Scheduled launchBooleanRule: launch_time after target datetime
Ring deploymentBooleanMultiple segment rules in priority order
Feature dependencyBooleanPrerequisites on parent flag