DEV Community

Jack
Jack

Posted on

Building a Feature Flags API from Scratch with FastAPI

Building a Feature Flags API from Scratch with FastAPI

Feature flags are one of those tools that seem simple until you implement them. I recently built FlagBit, a feature flags API, and wanted to share the interesting technical decisions.

Why Another Feature Flags Service?

The market is polarized: LaunchDarkly ($10/seat/mo) for enterprises, Unleash (self-hosted) for teams with DevOps capacity. Nothing in between for small teams that want a hosted API without per-seat pricing.

The Core: Flag Evaluation

The evaluation endpoint is the heart of any feature flags system. Here's the logic:

def evaluate_flag(flag, context):
    # 1. Check if flag is enabled at all
    if not flag.enabled:
        return False, "disabled"

    # 2. Check targeting rules
    for rule in flag.rules:
        if matches_rule(rule, context):
            # Percentage rules use consistent hashing
            if rule.operator == "percent":
                hash_val = consistent_hash(context["user_id"], flag.key)
                return hash_val < rule.value, "percentage_rollout"
            return True, "targeting_match"

    # 3. Fall back to default
    return flag.default_enabled, "default"
Enter fullscreen mode Exit fullscreen mode

Consistent Hashing for Percentage Rollouts

The trickiest part is percentage rollouts. If you roll out a feature to 30% of users, each user needs to consistently get the same result. Random sampling won't work — user A might see the feature on one request and not the next.

The solution: hash the user ID + flag key, map it to 0-100:

import hashlib

def consistent_hash(user_id: str, flag_key: str) -> float:
    raw = f"{user_id}:{flag_key}"
    digest = hashlib.sha256(raw.encode()).hexdigest()
    return (int(digest[:8], 16) / 0xFFFFFFFF) * 100
Enter fullscreen mode Exit fullscreen mode

This gives deterministic results: same user + same flag = same hash = same experience. And the distribution is uniform enough for practical purposes.

Targeting Rules Engine

FlagBit supports 5 operators:

  • eq / neq: exact string match
  • contains: substring match
  • in: value exists in a list
  • percent: consistent hash percentage

Rules evaluate against a context object that clients pass with each request:

{
  "flag_key": "premium-feature",
  "context": {
    "user_id": "usr_123",
    "plan": "pro",
    "country": "US"
  }
}
Enter fullscreen mode Exit fullscreen mode

A flag can have multiple rules. First match wins.

API Design Decisions

No SDK required. The entire API is one POST endpoint. Any HTTP client works. This was deliberate — SDKs add complexity, version management, and language lock-in.

SDK keys vs API keys. FlagBit uses two key types: API keys (full access, for management) and SDK keys (read-only, for evaluation). SDK keys are safe to embed in client-side code.

Single evaluation endpoint. Some systems have batch evaluation (evaluate all flags at once). FlagBit keeps it simple: one flag per request. At <50ms per evaluation, this is fast enough for most use cases.

What I Learned

  1. Consistent hashing is essential for any percentage-based feature. Random sampling causes flickering.
  2. Rule evaluation order matters. Document it clearly or users will be confused.
  3. API keys should be hashed in storage. Show the key once at creation, store only the SHA-256 hash.
  4. SQLite is fine for a feature flags service. The read pattern (evaluate) vastly outweighs writes (flag updates).

Try It

FlagBit is live at flagbit.anethoth.com with a free tier (5 flags, 1 project). The API docs cover everything.

I'm part of the Anethoth product studio — we also build DocuMint (PDF invoice API) and CronPing (cron job monitoring).

Questions or feedback? Drop a comment below.

Top comments (0)