Copy link to headingWhy do feature flags pile up in your codebase and never get deleted?
Feature flags began as on/off switches. You shipped code dark, flipped a toggle, and watched what happened. That model held up when teams deployed weekly and tracked a dozen flags by hand.
It breaks once two conditions change, and they change together:
Deployment frequency climbs. Continuous delivery pipelines push releases from weekly to daily to on-every-merge, which means more experiments, more gradual rollouts, and more kill switches per cycle.
Agents enter the deployment path. AI coding agents now initiate over 30% of deployments on Vercel, up 1,000% in six months, removing humans from the review loop on individual releases.
More flags get created faster, by more parties, with less manual oversight at each step. The dozen flags you tracked in a spreadsheet become hundreds with no clear owner and no structural pressure to remove them.
The conventional approach to feature flagging optimizes for creation. The toggle is a dashboard click. The SDK evaluation is milliseconds. The removal has no path at all, because the tooling was built for the moment of evaluation, not the months that follow once a rollout is done.
That gap is where the damage accumulates. Evaluation happens once, at request time, and either works or it doesn't. Lifecycle failure compounds silently: every flag left in place adds code paths, branches the test surface, and increases the cognitive overhead required to reason about what your system does in production.
This article is about that failure mode and the architectural responses that fix it: flags defined in version-controlled code, evaluated at the edge, and consumed by agents with the same safety guarantees humans get.
Copy link to headingKey takeaways
Flag lifecycle is a structural incentive problem, not a tooling gap. Stale-flag dashboards surface the mess without changing the incentive that produced it.
Flags defined in code make deletion a reviewable code change, which is the only mechanism that moves cleanup out of the someday pile and into the pull request queue.
Client-side flag evaluation introduces a CLS tax most teams never measure. Edge-based evaluation via Edge Config eliminates it without forcing dynamic rendering, returning reads in under 5 ms on most lookups.
Over 30% of deployments on Vercel are now initiated by coding agents, up 1,000% in six months. At that velocity, canary rollout with automatic rollback becomes the default safety mechanism the system needs to function.
Flags-as-code, edge evaluation, and agent-native rollouts appear to be three separate improvements. They converge on one separation of concerns: definition in code, evaluation at the edge, management in the best tool for that job, and cleanup enforced by the build.
Copy link to headingFlag lifecycle is the real failure mode
The feature flag industry keeps treating evaluation as the primary problem. Which SDK has the lowest latency? Which dashboard has the most expressive targeting rules? Those are fine questions, and they are also the wrong place to spend your attention.
I've watched teams build genuinely sophisticated evaluation infrastructure and then slowly drown in the flags that infrastructure made it easy to create. The creation path is frictionless by design. Removal has no path at all.
Copy link to headingThe combinatorics problem
Ten flags produce 1,024 possible code paths. Twenty flags push that past a million. You cannot test a million paths, and you cannot reason about what your production system does once the combinatorics outrun your mental model of it.
The failure mode is rarely a flag behaving incorrectly. More often, it is a flag behaving correctly in a context nobody remembered to account for.
Knight Capital's 2012 trading loss is the clearest example of what this costs. A developer reused an old "Power Peg" flag rather than creating a new one. That flag woke up deprecated code from 2003, which had been parked behind a toggle for nearly a decade. The flag did not cause the loss on its own. The decade of nobody removing it did.
Copy link to headingThe cleanup incentive problem
Flag cleanup is a structural incentive problem, not a tooling gap, and the difference matters: structural problems require architectural fixes, while tooling gaps can be patched with better dashboards.
The reason is timing. A flag is top of mind exactly when it is most useful. Once a rollout completes and the flag recedes from active attention, the off-state may already be broken, the original author has moved on, and nobody has standing to own the removal.
New features beat cleanup every time in this environment:
Cleanup has no deadline.
Cleanup has no demo.
Cleanup has no sprint ticket.
Stale-flag dashboards and warning banners surface the mess without changing the incentive that produced it, which is why flag counts keep climbing regardless of how prominent the warnings are.
Cleanup has to become structurally mandatory. Architecture makes forgetting impossible. The next three sections cover what that looks like in practice.
Copy link to headingThe three failure modes and their fixes
The lifecycle problem has three distinct failure modes, each with its own root cause and architectural response.
The three fixes are independent: you can adopt any one without the others. They reinforce each other, though.
Edge evaluation reaches its full potential when the flags it reads are defined in code and version-controlled. Canary rollouts work reliably only when the flag controlling the canary cohort has a clear definition, a clear owner, and a clear removal plan once the rollout completes.
Copy link to headingFlags belong in code
Most teams put flags in a SaaS dashboard because product managers need toggle access without a deploy. That is a reasonable constraint. It is also the wrong place to hold the flag's definition, because a definition stored only in a dashboard has no version history, no reviewer, and no structural path to deletion.
I've seen what happens when the definition and the toggle live in the same place:
The toggle gets used constantly.
Targeting rules accumulate and drift from the original intent.
Removal never happens because nobody owns the definition. Nobody owns the definition because it was never part of the codebase to begin with.
The Flags SDK inverts this. The flag() function defines flags in TypeScript, giving each flag a commit, an author, a pull request, and a diff. Deleting the flag is a code change. It appears in the diff, goes through review, and lands in commit history. The decision to remove a flag becomes as visible and as accountable as the decision to add one.
Copy link to headingDeletion as a code change
Once flag deletion requires a pull request, it acquires the properties that make code changes accountable:
A reviewer must approve it.
The CI pipeline runs against it.
The commit record shows who did it and when.
A flag with a maxAge that fails the build after it expires is a categorically different kind of accountability than a stale-flag warning sitting in a dashboard nobody opens.
Automated cleanup is starting to appear in the tooling layer: Atlassian built an AI cleanup workflow for flag removal using Rovo Dev, and Gitar reports working with companies that introduce hundreds of flags per month, with thousands already accumulated. The enforcement mechanism is still the build, not the warning. The build fails rather than advises.
Copy link to headingWorking with providers and the OpenFeature adapter
Flags-as-code raises an obvious objection: developers do not want to leave their editor to change a flag value while working locally. The old loop is slow: you leave the editor, sign in to the flag provider, hunt for the right flag, switch the value, then coordinate that change with teammates who depend on it.
The Flags Explorer in the Vercel Toolbar removes that round trip. Overrides live in an optionally encrypted cookie, so your application honors them without ever calling the provider. The toolbar can suggest overrides to teammates working on a branch locally or testing a Preview Deployment.
Dashboards still earn their place: product managers keep the toggle access they need, engineers keep the version history they need, and the two concerns no longer compete for the same interface.
The Flags SDK ships a native OpenFeature adapter, so flag definitions are written once and work across providers without rewriting evaluation logic. Supported providers include:
LaunchDarkly, Statsig, Hypertune, Split, Optimizely
PostHog, DevCycle, GrowthBook
AB Tasty, Bucket, Cloudbees, ConfigCat, FeatBit, flagd, Flipt, GO Feature Flag, Kameleoon, and more
Dynatrace's acquisition of DevCycle reads as enterprise capital betting on exactly this direction: portable evaluation that moves across providers rather than locking a team to one. The Flags SDK is free and open-source for the same reason: the evaluation layer belongs as a platform primitive, not a product you rent.
Copy link to headingEdge evaluation and precomputed variants
Client-side flag evaluation carries a performance cost most teams never put on the books. Client-side SDKs evaluate flags in JavaScript in the browser, so flags must load before components render. Miss that window, and the page shifts under the user.
This is Cumulative Layout Shift, and it is a Core Web Vitals signal with direct SEO consequences. I've watched teams spend engineering cycles grinding their Core Web Vitals into shape, then bolt a client-side experimentation layer on top that quietly undoes that work.
Moving evaluation server-side at the origin trades one problem for another. The application server and the flag provider API typically reside in different regions, introducing round-trip latency on every request. You eliminated layout shift and added a bottleneck in the critical path.
Edge-based evaluation sidesteps both. Edge Config is a globally distributed store where flag state replicates to every region before any request arrives:
Most reads return in under 5 ms, with 99% under 15 ms.
Many reads resolve locally at the edge node, eliminating the network round trip entirely.
Flag state propagates globally in under 10 seconds when toggled.
Sub-millisecond reads and seconds-scale writes are exactly the right asymmetry for feature flag configuration: evaluation needs to be instantaneous, and a few seconds of propagation lag when a flag changes is acceptable.
Speedway Motors moved from client-side to edge-based evaluation through Edge Config and cut Cumulative Layout Shift by 50%.
Vercel has partnered with LaunchDarkly, Statsig, Hypertune, Split, and Optimizely to sync flag definitions directly into Edge Config. Flag state changes are pushed from the provider into Edge Config, and Routing Middleware reads them at request time without calling the provider's infrastructure.
Copy link to headingWhy client-side evaluation costs more than you think
The CLS problem is visible when it occurs and measurable afterwards. The harder costs accumulate before anyone notices:
Sensitive flag logic (targeting rules, user segment definitions, experiment configurations) lives in the browser where anyone can read it.
Every user on a slow connection waits for the flag payload before the page stabilizes.
Your Core Web Vitals are only as good as your slowest flag provider response.
Teams in this situation are usually in one of two positions: they haven't measured the CLS impact yet, or they've measured it and accepted it as the cost of experimentation. The second position is defensible if the alternative is no experimentation at all. It stops being defensible once edge-based evaluation is available, because you are paying a performance tax for a constraint that no longer exists.
Copy link to headingPrecomputed variants and cache invalidation
A common assumption about server-side evaluation is that it forces every flagged page to be rendered dynamically, trading CLS for cache misses. The precompute pattern breaks that assumption.
The Flags SDK's precompute pattern generates multiple versions of static pages, one for each flag-value combination. Routing Middleware routes each request to the correct pre-rendered variant based on evaluated flag state. The result:
The page stays static and CDN-cached.
Evaluation stays server-side.
CLS stays at zero.
This holds even when multiple feature flags and experiments share the same page.
The stabilization of Cache Components in Next.js 16 makes this production-ready without caveats. With Partial Prerendering, Next.js renders statically until the application reaches for incoming request data like cookies or headers, then carves out the smallest possible dynamic slice while keeping the rest static.
The static shell stays eligible for ISR revalidation. The cacheTag and revalidateTag patterns trigger cache invalidation the moment a flag is toggled and propagate the new content to every CDN region through a global push pipeline. Visitors get the cached version while regeneration runs in the background, and the update lands without a full redeploy.
Vercel uses this internally. The Flags SDK and AI SDK together power the evaluation of different AI providers for generating UI in v0. Flag values are always calculated on the server; the resolved value can be passed to the client, but the evaluation itself never moves browser-side.
Copy link to headingAgents as flag consumers
Over 30% of deployments on Vercel are now initiated by coding agents, up 1,000% in six months. At that velocity, the human review loop that used to catch bad deployments before they reached production is no longer reliably in the path. A broken change can reach users before any engineer has seen it.
The ability to turn something off without a redeploy is what separates an agent mistake from a production incident.
The Flags SDK is built for this. The Flags SDK skill lets an agent generate and manage flags from natural language:
npx skills add vercel/flags
A safe-rollout skill wires the flag, generates a rollout plan with rollback conditions, and defines how to verify the change behaves as expected. The agent runs it, meaning the rollout procedure is executed rather than approximated.
Progressive delivery follows the same logic as agent velocity. The standard pattern is a 1% canary cohort: monitor through that phase, and if error rates spike, the flag goes off immediately with no new deployment and no git revert needed.
When a human runs that loop, it is a disciplined practice. When an agent runs deployments continuously, canary-with-automatic-rollback becomes the default safety mechanism the system requires to function.
Copy link to headingOperational knowledge as a runnable tool
The deeper shift is about where operational knowledge lives.
In most organizations, the rollout procedure for a new feature is a wiki page:
A checklist of steps
Rollback conditions
Monitoring thresholds
Escalation paths
Engineers consult it, interpret it, and execute it by hand. The procedure is only as good as the last person who updated it, and no more reliable than the engineer reading it at 2am.
A skill that wires a flag, generates a rollout plan with rollback conditions, and specifies how to verify the change is a different artifact. It is a runnable encoding of the procedure: an agent executes it with the same fidelity at 2am as at 2pm, and an engineer can inspect it the same way they inspect code.
The operational knowledge moves into the codebase, where it is version-controlled, reviewable, and enforceable. That is the same argument that makes flags-as-code compelling for lifecycle management.
Copy link to headingWhere this framework falls short
Flags-as-code, edge evaluation, and agent-native rollouts solve real problems. They also introduce tradeoffs worth naming before you hit them in production.
Copy link to headingFlags-as-code adds commit friction
Writing a flag definition, committing it, and putting it through review is friction that a dashboard toggle does not have. For small teams running short-lived experiments, that friction is real. The Flags Explorer removes the round-trip cost during local development, but the commit-and-review cycle remains.
The commit friction pays for itself once flag accumulation becomes a problem or compliance requires an audit trail. For a two-person team shipping a weekend project, a dashboard is probably fine.
Copy link to headingDashboard coexistence requires explicit ownership
Flags-as-code works when engineers own the definition and product managers own the toggle. That split only holds if both sides understand and respect it.
I've seen it collapse when a product manager edits targeting rules in ways that drift from the code-defined intent, and the two definitions slowly diverge without anyone noticing. Explicit documented ownership prevents this; assumed ownership reliably does not.
Copy link to headingEdge Config has a write propagation ceiling
Sub-10-second global propagation is the right trade-off for feature-flag configuration. It is the wrong tool for real-time transactional data, inventory systems, or any workload where a stale state for a few seconds produces incorrect business outcomes. Teams that use Edge Config as a general-purpose, low-latency store will hit this ceiling.
Copy link to headingEnforced expiry still requires discipline at creation time
A flag with a maxAge that fails the build after expiration is a powerful mechanism, but it requires setting the maxAge at creation time, at exactly the moment when the flag feels most useful, and the removal date feels furthest away. The tooling to make this automatic is emerging, but it is not yet solved out of the box.
Copy link to headingWhat comes next
Flags defined in application code, evaluated at the Global Network edge, observed through deployment analytics, and consumed by agents are one system. Treating them as separate concerns imposes a coordination cost that the architecture would eliminate.
Lifecycle management is the piece still unsolved at scale. Automated cleanup is starting to appear: Atlassian built an AI cleanup workflow using Rovo Dev, and Gitar reports that companies are introducing hundreds of flags per month, with thousands already accumulated.
The pattern that works is enforced lifecycles: architecturally mandated expiration where the build fails rather than warns. Flags defined in code make that possible in a way dashboard-managed flags never will, because a code artifact can carry a contract in a way a dashboard entry cannot.
Flags-as-code, edge evaluation, and agent-native rollouts share the same underlying structure: each concern is handled by the layer best suited to handle it.
Definition in code.
Evaluation at the edge.
Management in the best tool for that job.
Cleanup enforced by the build.
The teams that get this right are not trying to make their flag dashboard more powerful. They are pulling the concerns apart and assigning each one to the layer that handles it best.
Copy link to headingFAQ
Does the Flags SDK require a third-party feature flag provider?
No. The Flags SDK works with any flag provider, custom setups, or no provider at all. You define flags in code with the flag() function and a decide function that returns the flag's value. Provider adapters are available for LaunchDarkly, Statsig, Hypertune, Split, and the full OpenFeature ecosystem when you want them.
How does edge-based flag evaluation affect write propagation?
Changes to Edge Config propagate globally within 10 seconds. Reads return in under 5 ms for most cases, with 99% under 15 ms. That asymmetry is by design: it fits the feature-flag configuration, where sub-10-second propagation is acceptable, but it is a poor fit for real-time transactional data.
Can precomputed flag variants work with multiple flags on the same page?
Yes. The precompute pattern generates multiple versions of static pages with different flag combinations, and Routing Middleware routes each user to the correct variant based on the evaluated flag state. It holds even with multiple feature flags and experiments on a single page, with zero layout shift.
Which frameworks does the Flags SDK support?
The Flags SDK is built for Next.js (App Router, Pages Router, Routing Middleware) and SvelteKit, with full TypeScript support and type inference. The official source of truth for the SDK is flags-sdk.dev.