On this page
How feature flags work
Feature flags are backed by PostHog and shared across every surface: the Rust gateway, the settlement pipeline, the SDKs, and the dashboard. This page is the authoritative standard — surface-specific tasks cite it for flag names and for where a flag is evaluated. It does not implement evaluation anywhere; each surface owns that.
Naming convention
Every flag key follows <surface>.<area>.<feature>, where
surface ∈ {gateway, settlement, sdk, dashboard}. Keys are lowercase,
dot-separated, and carry no version numbers — versions belong in PostHog
variants, not in the key. The area names the subsystem inside the surface; the
feature names the behaviour being gated.
One example per surface:
gateway.matching.batch-dispatchsettlement.ledger.async-reconcilesdk.retry.adaptive-backoffdashboard.orderbook.depth-chart
A team member can name a new flag for any surface from these rules alone: pick the surface, name the area, name the feature, keep it lowercase and dotted, and leave versioning to variants.
Rollout strategy patterns
Two patterns are supported. Do not invent others.
- Percentage rollout — release to a growing share of the audience (1% → 10% → 50% → 100%). Backed by PostHog's rollout percentage on the flag. Use it when the change is broadly applicable and you want to observe blast radius before full exposure.
- User-segment targeting — release to a defined cohort (for example a seller tier, an internal team, or a named account) regardless of percentage. Backed by PostHog release conditions on person/group properties. Use it when the change should reach a specific audience first, such as dogfooding or a design-partner preview.
The two compose: a flag can target a segment at 100% while the general population sits at a lower percentage.
Lifecycle: create → percentage rollout → full rollout → cleanup
- Create. Entry: a change ready to ship behind a gate. The owning team creates the flag in PostHog under the naming convention, defaults it off, and merges the gated code. Exit: the flag exists and the code path is inert in production.
- Percentage rollout. Entry: the gated code is deployed and off. The owning team raises the rollout percentage (or enables a target segment) in stages, watching for regressions between steps. Exit: the flag is enabled for its full intended audience with no outstanding regressions.
- Full rollout. Entry: the flag has held at its full audience without regression through a soak period the team judges sufficient. The behaviour is now the default expectation. Exit: the gated path is confirmed stable and the flag no longer changes anyone's experience.
- Cleanup. Entry (the exit signal that permits cleanup): the flag has been at stable full rollout with no regression. The owning team removes the flag in PostHog and deletes the dead code branch/gate — the flag check, the now-unreachable branch, and any config it required — so no stale gate or dead path remains. A flag that ships is a flag that gets removed; leaving the gate in place is not a valid end state.
Canary rollback (PostHog metrics driving an automated rollback) is a separate concern; see the canary rollback concept page for that flow.
Where each surface evaluates flags
Each surface evaluates flags at a fixed location so teams pick the right path.
Server-side surfaces call the PostHog HTTP API directly; the dashboard uses
posthog-js in the browser.
| Surface | Where it evaluates | How |
|---|---|---|
| Rust gateway | Server-side | Direct PostHog HTTP API via the hyper HTTP/1 client pattern in gateway/src/proxy.rs |
Settlement pipeline (ledger) | Server-side | Direct PostHog HTTP API inside the consumer loop |
Rust token-gateway-sdk and JS/TS SDKs | Server-side | Direct PostHog HTTP API |
| NextJS dashboard | Client-side | posthog-js, layered on the PostHogProvider at apps/dashboard/src/components/posthog-provider.tsx |