How it fits together
Flaghoist is a small set of composable pieces. Understanding how they connect makes the rest of the docs obvious.
The two halves
Section titled “The two halves”The flag service is deployed once for your team and lives in your infrastructure. It is a Hono app, so the same code runs on Cloudflare Workers, Node, Bun, Deno, or in a container. It exposes:
- the OFREP read path (
POST /ofrep/v1/evaluate/flags) for apps to evaluate flags, - the admin API (
/api/v1/flagsand the routes around it) for managing them, - the dashboard at
/admin.
Apps read flags with an API key. People manage them with the admin token or, once you turn on accounts, with their own sign-in and role.
Your apps consume flags through OpenFeature. A provider fetches evaluated booleans from the
service; your code calls getBooleanValue('flag', false) and never depends on Flaghoist directly.
Evaluation
Section titled “Evaluation”Each flag is evaluated as an ordered cascade: the same logic on every runtime and language, because
it happens server-side in @flaghoist/core:
- If the flag is disabled, serve off.
- Walk targeting rules top to bottom; the first whose conditions all match decides the result (optionally gated by a per-rule percentage).
- If no rule matches, fall through to the flag’s default rollout percentage.
Percentage rollouts are sticky: sha256(targetingKey + ":" + flagKey) % 100 < percentage, so a
given user always gets the same answer for the same flag, with no assignment state stored anywhere.
Storage
Section titled “Storage”Storage is pluggable behind a four-method interface (get / put / delete / list). Adapters
for Cloudflare KV, Redis, Postgres, SQLite and memory ship with Flaghoist; anything else is a small
adapter you write. Accounts, sessions, invites and access tokens live in the same storage, through
an optional record store every bundled adapter has. See storage adapters.
The read path caches flag definitions in-isolate, so a burst of evaluations does not hammer
storage: at most one list() per cache window.
No vendor lock-in
Section titled “No vendor lock-in”Because every call site is standard OpenFeature, moving to (or from) LaunchDarkly, Datadog, or any OFREP-compatible backend is a one-line provider swap with zero changes to your application code.