Feature flags
built for great DX
Feature flags as code. Strongly typed, Git-friendly, and built to eliminate string-based errors.
❯
EVERYTHING THE TYPE SYSTEM NEEDS
Six primitives that cover the whole lifecycle from definition to rollout
One file. Total control.
Define your flags in TypeScript. VoidFlag derives every type, every fallback, every constraint from that one file — nothing lives in a dashboard you can't version.
// voidflag.schema.ts
export const schema = defineFlags({
darkMode: boolean().fallback(false),
theme: string().fallback('light'),
fontSize: number().fallback(16),
});Schema → generate → push → apply.
The entire lifecycle runs through vf. Generate a typed state file, push your schema to the server, then apply it to any environment. No UI required.
# scaffold schema + config
vf init
# generate voidflag.state.ts from schema
vf generate
# sync schema with the server
vf push
# apply state to an environment
vf apply --env stagingPick the right accessor for the job.
get() resolves the value once. flag() returns a live accessor that always reflects the current store. flags.x is shorthand for flag(). same live accessor with dot access. accessors are created lazily and cached, so no extra allocations.
// get() — resolved value, one shot
const value = client.get('darkMode');
// ^? boolean
// flag() — live accessor object
const f = client.flag('theme');
f.value; // enabled ? value : fallback
f.fallback; // 'light'
f.enabled; // true
f.rollout; // 100
// flags.x — lazy shorthand for flag()
client.flags.fontSize.value;
client.flags.darkMode.enabled;The compiler knows your flags.
Every accessor is typed to its exact primitive — no casting, no any. Typos and wrong types are compile errors before they ship.
client.get('darkMode'); // boolean
client.get('theme'); // string
client.get('fontSize'); // number
// Typos don't compile.
client.get('darkMood');
// ~~~~~~~~~
// Argument of type '"darkMood"' is not
// assignable to parameter of type 'keyof S'.Flags as injection decision points.
Use flag state to resolve which implementation gets injected at runtime. Swap strategies, migrate dependencies, or A/B test entire service layers — no redeploy, just flip the flag.
// swap payment provider at runtime
const paymentService = client.flags.useStripe.value
? new StripeService()
: new PayPalService();
container.register(PaymentService, paymentService);
// gradual migration — stable per user
const service = client.isRolledOutFor('useStripe', user.id)
? new StripeService()
: new PayPalService();Gradual. Deterministic. Reversible.
Roll out to a percentage of your users with a stable hash — same user, same result, every time. Dial up, dial back, or kill-switch from the state file.
// 20% rollout — deterministic per user
client.isRolledOutFor('darkMode', user.id);
// user_42 → bucket 17 → true ✓
// user_99 → bucket 83 → false
// allEnabled() — gate on multiple flags at once
client.allEnabled(['darkMode', 'newCheckout']);
// false if any flag is disabledlive demo
Select a flag · tune its props · watch users resolve to value or fallback
A/B test: which hero copy does this user see?
"control" | "challenger"STOP SHIPPING FLAGS YOU CAN'T TRUST.
Runtime flags are silent, untyped, and untraceable. VoidFlag makes them compile-time citizens.
- Typo compiles fine, fails at runtime
- Undefined flags return false silently
- No types for values or variants
- Changes in audit logs, not Git
- Unknown flags won't compile
- Schema-defined, build-time types
- Strict values and metadata
- Versioned state reviewed in PRs
Built for the TypeScript ecosystem.
Backend-first today. Expanding to more runtimes soon.
Node.js
Full runtime support
Express
Works inside route handlers
NestJS
Module integration
Next.js
Server-side & Edge
Bun
Deno
.NET
Go
Java
Python
FLAGS TREATED LIKE CODE
Typed at build time. Versioned in Git. Controlled without redeploys.
Flags live in a schema file inside your repo — not in a dashboard. They exist at build time and generate types automatically.
Undefined flags don't silently return false. They throw at compile time. Misuse is caught before it reaches production.
State changes are versioned, reviewed in PRs, and traceable. No more hunting through audit logs.
Think Prisma-style schema discipline applied to feature flags. VoidFlag is built for teams who want strictness, not chaos.
join the waitlist
be first when voidflag ships
no spam · unsubscribe anytime