DEV Community

Jack
Jack

Posted on • Originally published at anethoth.com

Feature Flags Explained: Ship Code Without Breaking Everything

You just deployed a new feature and it's breaking everything. Users are complaining. Your boss is asking questions. You're frantically trying to roll back.

Feature flags would have prevented this. Here's how they work and how to implement them — even if you've never used them before.

What Are Feature Flags?

A feature flag is an if statement that wraps your new code:

if feature_enabled('new-checkout-flow', user_id='user_123'):
    return new_checkout()
else:
    return old_checkout()
Enter fullscreen mode Exit fullscreen mode

The flag is controlled by a configuration, not by your code. You can turn features on/off without deploying. You can roll them out to 10% of users first. You can target specific users for beta testing.

The Simplest Implementation

You don't need a paid service to start. A JSON file works:

{
  "new-checkout-flow": false,
  "dark-mode": true,
  "ai-search": false
}
Enter fullscreen mode Exit fullscreen mode
import json

def feature_enabled(flag_name: str) -> bool:
    with open('flags.json') as f:
        flags = json.load(f)
    return flags.get(flag_name, False)
Enter fullscreen mode Exit fullscreen mode

This is fine for a solo project. But it falls apart when you need:

  • Percentage rollouts — 10% of users first, then 25%, then 100%
  • User targeting — beta testers see the feature, everyone else doesn't
  • Instant toggles — turn off a broken feature in seconds, not deploy-minutes

Level Up: Percentage Rollouts

The key insight: hash the user ID to get a consistent number between 0-99. If the number is below your rollout percentage, the user sees the feature.

import hashlib

def is_in_rollout(flag_name: str, user_id: str, percentage: int) -> bool:
    # Hash user_id + flag_name for consistent bucketing
    key = f"{flag_name}:{user_id}"
    hash_value = int(hashlib.md5(key.encode()).hexdigest(), 16)
    bucket = hash_value % 100
    return bucket < percentage

# 10% rollout
is_in_rollout('new-checkout', 'user_123', 10)  # Always returns same result for same user
is_in_rollout('new-checkout', 'user_456', 10)  # Different user, different result
Enter fullscreen mode Exit fullscreen mode

The MD5 hash ensures the same user always gets the same result (no flickering between old and new), and users are distributed evenly.

You can try this interactively:

# Free API — simulate a rollout across 1000 users
curl -s 'https://flagbit.anethoth.com/api/v1/rollout/simulate?flag=new-checkout&percentage=25&user_count=100' | jq '.summary'
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "total_users": 100,
  "included": 25,
  "excluded": 75,
  "actual_percentage": 25.0
}
Enter fullscreen mode Exit fullscreen mode

Level Up: Targeting Rules

Sometimes you want a feature enabled for:

  • All users with plan: pro (beta features for paying customers)
  • Users in country: US only (compliance-gated features)
  • Your internal team emails (dogfooding)
def evaluate_flag(flag_config: dict, user_context: dict) -> bool:
    rules = flag_config.get('rules', [])

    for rule in rules:
        attribute = rule['attribute']  # e.g., 'plan'
        operator = rule['operator']    # e.g., 'equals'
        value = rule['value']          # e.g., 'pro'

        user_value = user_context.get(attribute)

        if operator == 'equals' and user_value == value:
            return True
        elif operator == 'contains' and value in str(user_value):
            return True
        elif operator == 'in' and user_value in value:
            return True

    # Check percentage rollout as fallback
    percentage = flag_config.get('percentage', 0)
    if percentage > 0:
        return is_in_rollout(flag_config['name'], user_context.get('id', ''), percentage)

    return flag_config.get('enabled', False)
Enter fullscreen mode Exit fullscreen mode

You can test targeting rules without writing code:

# Free playground — no signup required
curl -s -X POST 'https://flagbit.anethoth.com/api/v1/evaluate-playground' \
  -H 'Content-Type: application/json' \
  -d '{
    "flag": {"name": "new-checkout", "enabled": true, "rules": [{"attribute": "plan", "operator": "eq", "value": "pro"}]},
    "context": {"plan": "pro", "country": "US"}
  }'
Enter fullscreen mode Exit fullscreen mode

When to Use Feature Flags

Yes:

  • Risky features (payment processing changes, auth changes)
  • Gradual rollouts (new UI, new algorithms)
  • A/B tests (try two approaches, measure which converts better)
  • Kill switches (turn off a feature that's causing errors)
  • Premium features (flag check = plan check)

No:

  • Trivial changes (copy updates, CSS tweaks)
  • Features you're 100% shipping to everyone
  • Temporary debugging code

The Progressive Rollout Strategy

Here's the rollout pattern used by companies like GitHub, Stripe, and Netflix:

  1. 0% — Feature merged behind a flag. Only visible to developers.
  2. Internal — Enable for your team via targeting rule (email contains @yourcompany.com)
  3. 1% — Canary release. Watch error rates and metrics.
  4. 10% — Wider canary. Enough traffic to spot edge cases.
  5. 50% — Half your users. Compare metrics between control and treatment.
  6. 100% — Full rollout. Remove the flag from code in the next sprint.

The key: increase slowly, monitor at each step, and have a one-click killswitch.

Choosing a Feature Flag Tool

Tool Price Best For
JSON file Free Solo projects
FlagBit Free–$49/mo Small teams, API-first
LaunchDarkly $10/seat/mo Enterprise
Unleash Free (self-host) Control freaks
Statsig Free tier A/B test focused

Quick Start

Want to try feature flags right now? Here's a 30-second setup:

# 1. Sign up (free, no credit card)
curl -s -X POST https://flagbit.anethoth.com/api/v1/signup \
  -H 'Content-Type: application/json' \
  -d '{"email": "dev@example.com"}'

# 2. Create a project
curl -s -X POST https://flagbit.anethoth.com/api/v1/projects \
  -H 'X-API-Key: YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name": "my-app"}'

# 3. Create a flag
curl -s -X POST https://flagbit.anethoth.com/api/v1/projects/PROJECT_ID/flags \
  -H 'X-API-Key: YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name": "new-checkout", "enabled": false}'

# 4. Evaluate in your app
curl -s 'https://flagbit.anethoth.com/api/v1/evaluate?sdk_key=SDK_KEY&flag=new-checkout&user_id=user_123'
Enter fullscreen mode Exit fullscreen mode

That's it. You now have a feature flag system. Turn features on/off from the API, roll out to percentages of users, and target specific user segments.


Resources:

Top comments (0)