flaggator

Open source · self-hosted · HTTP API

Feature flags that stay on your machine.

flaggator is a feature-flag service you run yourself. One local process serves the HTTP API, and every behavior the service offers goes through that API: projects, environments, flags, targeting, and evaluation.

127.0.0.1 Default listen address. One Python process.
SQLite or MySQL SQLite from the standard library. MySQL is optional.
/v1 Versioned JSON API. Public keys in the path, not row ids.

What you model

A project holds flags and environments. Variations belong to the flag. Targeting belongs to one environment, so a flag can be on in dev and off in prod.

Flags and variations

A flag has an immutable key, a name, a description, and an ordered list of JSON values. The index is the variation’s identity. Booleans, numbers, strings, arrays, and objects are all ordinary values.

Per-environment targeting

Each environment stores whether the flag is on, the off variation, individual targets, ordered rules, a fallthrough, prerequisites, and a config version. A new environment starts with every existing flag disabled.

Rules, then a rollout

The first matching rule wins, and every clause in that rule must match. A rule can serve one variation or a percentage rollout. Rollouts hash flag:salt:context key with SHA-256, so the same person stays in the same bucket.

Prerequisites

A flag can require another flag in the same environment to evaluate to a given variation before its own rules run. Cycles are rejected on write. If a prerequisite fails, the off variation is served.

Two credentials

There are no user accounts. A bearer token is the caller. Secrets are stored as hashes and shown in plaintext only once, when the key is created.

Management tokenSDK key
Creates and edits projects, environments, flags, and targeting. Can read the audit log. Bound to one environment. Evaluates flags and reads that environment’s evaluation config.
May also evaluate, so an operator can debug a flag. Must name the project and environment. Cannot mutate. A mismatched project or environment on the request is forbidden.

Writes leave a record

Replacing targeting sends the version the client read. A stale version is a conflict, so two editors cannot silently overwrite each other. The client reads again and retries. Mutations are audited: actor, action, and the before and after documents. The secret itself is never written to the log.

GET /health is the only route without a token. It reports that the process is up and does not check the database.

Evaluation order

The same configuration and the same context always produce the same decision. Time and randomness are not inputs. Order is off, prerequisites, targets, rules, then fallthrough. This example has no prerequisites. The page runs it in the browser and does not call a server.

checkout-v2 · prod · version 7

  • Variations: 0 = false, 1 = true.
  • Target: context key alice serves variation 1.
  • Rule r1: country in ["IT", "FR"] serves a rollout, salt s1, 10% variation 1 and 90% variation 0.
  • Fallthrough and the off variation are both variation 0.

Decision

—

variation
—
reason
—
rule
—
bucket
—
1 off 2 target 3 rule 4 fallthrough

How the process is built

Controllers stay thin. A handler parses the request, calls one domain service, and writes the response. Business rules do not live in SQL or in the HTTP layer.

API first Behavior is the versioned HTTP API. A user interface, if one is added, is a client of that API.
Explicit SQL Repositories send SQL text and bind parameters. Rows map to dataclasses. There is no ORM.
Standard library first HTTP, JSON, hashing, and SQLite come from Python. MySQL is the one optional driver.
Secure by construction Credentials are scoped and hashed. Flag rules are data, interpreted by the evaluator. SQL values are bound parameters.

Where v1 stands

The connection layer, schema migrations, in-memory cache, GET /health, management tokens, projects, environments, and flags are in place. python -m main bootstrap creates a management token. The process does not listen for requests yet. SDK keys, targeting writes, the audit log, and the evaluate routes are specified and not served yet. The license is not chosen yet.

github.com/frncscsrcc/flaggator