What is a feature flag, and how do you test on just you?
In one sentence:A feature flag is a switch stored outside your code, often an environment variable or a dashboard toggle, that turns a feature on or off without a new deploy.
What it actually is
A feature flag is a stored value, usually true or false, sometimes a percentage or a list of user IDs, that your code checks before deciding what to show or do. The check lives inside your code, something like if (flagIsOn), but the value that answers it lives outside: in an environment variable, a config file, or a dashboard from a service like LaunchDarkly, PostHog, or Vercel Flags. Change that value and the app’s behavior changes without a new deploy.
Think of it as a breaker panel. The wiring for every room in a house already exists before anyone moves in, and a breaker just decides which rooms currently get power. A flagged codebase works the same way: the old version of a feature and the new one can both already sit in the same shipped build. The flag is the breaker deciding which one actually runs for a given visitor, and you can flip it without touching a wire or shipping a new build.
Why your AI just did this
Your agent reaches for a flag whenever you ask for something like “let me try the new dashboard without showing it to everyone yet” or “roll this out slowly so we can watch for problems.” The version it can write fastest is a plain environment variable check, something like if (process.env.NEW_CHECKOUT === "true"). That’s a real feature flag, a homemade one, and it’s often exactly what a small project needs: one switch, one value.
Flags also let your agent ship code through your normal CI/CD pipeline without releasing what it contains. The feature merges and deploys behind a flag that stays off, so deploying the code and releasing the feature become two separate decisions.
For per-user targeting or a percentage rollout, your agent reaches for a dedicated provider instead, Vercel’s own Flags platform or a third party like LaunchDarkly or PostHog. Next.js adds one more detail worth knowing: an environment variable only reaches browser code if its name starts with NEXT_PUBLIC_. Everything else stays server-only. Get that prefix wrong and your flag either never reaches the component checking it in the browser, or leaks into the shipped JavaScript when it shouldn’t have.
When you’ll run into it
You’ll see it as a process.env check tucked inside a component or route, or a line in .env.local like NEXT_PUBLIC_SHOW_NEW_DASHBOARD=true. Flip that value locally, restart your dev server, and the feature appears on localhost. Push the same code live and nothing changes, because your hosting platform keeps its own copy of that variable, set separately from your local .env file, and it usually needs a new deploy before the change takes effect.
A real flag service skips that wait: flipping a value in LaunchDarkly, PostHog, or Vercel Flags takes effect instantly, no deploy. Their dashboards add their own vocabulary: a “rollout percentage” deciding what share of visitors see a variant, “targeting rules” keying off a user’s plan or ID, and a “kill switch”, the same flag used in reverse, shutting a feature off the moment it misbehaves. That’s often faster than a full rollback: flipping a value takes seconds, undoing a deploy drags back everything else that shipped alongside it.
What to check
- Find where the flag’s value is actually read: a bare
process.envcheck, or a call into an SDK from LaunchDarkly, PostHog, or Vercel Flags - If the feature touches data, payments, or access, confirm the same check exists on the server. A flag that only hides a button leaves the underlying route reachable to anyone who calls it directly
- Test the flag in its off state too. Old code sitting unused behind a flag is a common source of a nasty edge case once it becomes the only path left
- Confirm the flag’s name matches exactly, case included, between where it’s set and where it’s read
- Decide what the feature does if the flag service is slow or unreachable. A sensible default fails toward the safer, more restrictive state
- Once a flag has sat at 100 percent with nothing broken, ask your agent to remove it. A flag nobody flips anymore is just an if statement waiting to confuse the next person reading the file
Say it like a dev
Instead of: “let me try the new thing without anyone else seeing it” Say: “add a feature flag around this, an environment variable is fine for now, default it to off, and only show it when my user ID matches”
Instead of: “hide the beta button until it’s ready” Say: “hide it behind a flag on the frontend, and make the API route reject the request unless that same flag is on server-side, don’t just hide the button”
Instead of: “turn it off, something’s broken” Say: “flip the flag off instead of rolling back the whole deploy, that should be faster and won’t touch anything else we shipped”
People actually ask
“How do I turn on a new feature just for myself without breaking the app for everyone else?”
The simplest way is an environment variable your code checks before showing the feature, combined with a check against your own user ID or email so only you see it while the flag stays off for everyone else. A dedicated flag service like LaunchDarkly, PostHog, or Vercel Flags does the same job but lets you flip it from a dashboard and target specific users without touching a `.env` file.
“What's the difference between a feature flag and an environment variable?”
A plain environment variable is the simplest possible feature flag: your code checks one value like `process.env.NEW_CHECKOUT` and that value decides the behavior for everyone. A dedicated feature flag service adds targeting rules and percentage rollouts on top of that same idea, and lets you change the value instantly from a dashboard instead of editing a file and redeploying.
“Is it safe to hide an unfinished feature behind a feature flag?”
It's safe for hiding the UI, keeping a button or page out of view, but the flag alone doesn't protect the server route behind it. Anyone can call that endpoint directly with the same tools your app uses, so a feature that isn't ready for everyone needs the same check enforced on the server, not just a flag hiding the button in the browser.
Related terms
Checked against
Just met this in a real session? Glim reads it in plain words.
Paste what your agent just did, a git diff, your terminal, or its summary, and Glim tells you what changed and what to check before you ship. Nothing stored.
Explain my session →