<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: AvlCodeMonkey Industries</title>
    <description>The latest articles on DEV Community by AvlCodeMonkey Industries (avlcodemonkey-industries).</description>
    <link>https://dev.to/avlcodemonkey-industries</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F14409%2Fa8686fbe-b747-4568-a529-520bac194280.png</url>
      <title>DEV Community: AvlCodeMonkey Industries</title>
      <link>https://dev.to/avlcodemonkey-industries</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/avlcodemonkey-industries"/>
    <language>en</language>
    <item>
      <title>Build vs Buy: You Don't Need Another Side Project</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Wed, 02 Sep 2026 16:32:47 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/build-vs-buy-you-dont-need-another-side-project-2cgm</link>
      <guid>https://dev.to/avlcodemonkey-industries/build-vs-buy-you-dont-need-another-side-project-2cgm</guid>
      <description>&lt;p&gt;When you first need feature flags in a .NET application, the answer is wonderfully boring. Install &lt;code&gt;Microsoft.FeatureManagement&lt;/code&gt;, put some flags in &lt;code&gt;appsettings.json&lt;/code&gt;, and you're off to the races. Microsoft handles the feature evaluation plumbing, filters, targeting, and ASP.NET Core integration. And honestly?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That works great.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a small application with a handful of flags, you probably don't need anything more. Then things grow. Suddenly your &lt;code&gt;appSettings.json&lt;/code&gt; has become a feature management database with worse UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Configuration Becomes a Product
&lt;/h2&gt;

&lt;p&gt;The problem isn't evaluating a flag. That's easy. The problem is everything around it. What if a product manager wants to enable a feature without asking a developer? What if you want to change a flag without rebuilding and redeploying the application? What if you have multiple environments and enough flags that nobody remembers which configuration file is currently lying to them?&lt;/p&gt;

&lt;p&gt;At that point, you're not really managing configuration anymore. &lt;strong&gt;You're building a feature flag platform.&lt;/strong&gt; And that's where the build-vs-buy question gets interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  But AI Makes Building It Easy... Right?
&lt;/h2&gt;

&lt;p&gt;Well, yes. AI has made generating code dramatically cheaper. You can ask an AI to build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A feature flag API&lt;/li&gt;
&lt;li&gt;An admin UI&lt;/li&gt;
&lt;li&gt;A database schema&lt;/li&gt;
&lt;li&gt;An SDK&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Deployment scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...before your coffee gets cold. Congratulations. &lt;strong&gt;You have something that works.&lt;/strong&gt; You have not eliminated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintenance and security updates&lt;/li&gt;
&lt;li&gt;Hosting and infrastructure costs&lt;/li&gt;
&lt;li&gt;Backups&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Support and on-call&lt;/li&gt;
&lt;li&gt;Future-you wondering why past-you volunteered for this&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI reduces the cost of &lt;strong&gt;writing&lt;/strong&gt; software. It doesn't necessarily reduce the cost of &lt;strong&gt;owning&lt;/strong&gt; software. That's an important distinction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build vs Buy Isn't About Code
&lt;/h2&gt;

&lt;p&gt;The real question isn't:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can I build this?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course you can. The question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Do I want to keep building and maintaining this?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a very different question. If you're building a SaaS product, your engineering time is probably better spent on the things that give your product a competitive advantage. Not on building an admin interface for toggling booleans. Not on figuring out how to back up your feature flag database. Not on discovering that your homemade flag service has been down for three hours because nobody configured monitoring. And definitely not on becoming the proud maintainer of &lt;strong&gt;Yet Another Internal Platform™&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  So... Build or Buy?
&lt;/h2&gt;

&lt;p&gt;There isn't a universal answer. For a simple application with three flags?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Seriously. Microsoft already provides the feature management library. Put the flags in configuration and move on with your life. For a growing application where non-technical people need to safely manage features without touching JSON files or deployment pipelines?&lt;/p&gt;

&lt;p&gt;That's where a focused third-party solution starts looking pretty attractive. You get a proper management interface while your developers stay focused on building the actual product. That's the trade-off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build your product. Buy the plumbing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're looking for a simple way to manage .NET feature flags without turning feature management into another project, check out &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt;. Your developers will thank you. Probably.&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>dotnet</category>
      <category>softwaredevelopment</category>
      <category>ai</category>
    </item>
    <item>
      <title>Microsoft Feature Management Quirks (and How to Survive Them)</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Fri, 21 Aug 2026 16:33:44 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/microsoft-feature-management-quirks-and-how-to-survive-them-54d1</link>
      <guid>https://dev.to/avlcodemonkey-industries/microsoft-feature-management-quirks-and-how-to-survive-them-54d1</guid>
      <description>&lt;p&gt;&lt;code&gt;Microsoft.FeatureManagement&lt;/code&gt; is solid, widely used, and much better than building your own feature flag framework in a caffeine panic. But it has quirks. None are fatal. Most are avoidable if you know where the sharp edges are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Flag Names Are Strings Forever
&lt;/h2&gt;

&lt;p&gt;Feature names are strings. That means typos compile perfectly and fail at runtime in the most boring way possible. You configure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"FeatureManagement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_featureManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewDashbaord"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spot the typo? The compiler doesn't. Your shiny new UI never appears, and you spend an afternoon questioning your life choices.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Centralize your flag names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FeatureFlags&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;NewDashboard&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ExperimentalSearch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ExperimentalSearch"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use them everywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_featureManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FeatureFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDashboard&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or build a strongly typed wrapper if your application has enough flags to justify it. The important part is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stop scattering magic strings throughout your controllers, services, tag helpers, and filters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your typo budget is already being spent elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Shape Is Less Forgiving Than It Looks
&lt;/h2&gt;

&lt;p&gt;The library expects a specific configuration layout under &lt;code&gt;FeatureManagement&lt;/code&gt;. If you typo the section name, misconfigure &lt;code&gt;EnabledFor&lt;/code&gt;, or get creative with the JSON structure, your flags may not behave as expected. Then it looks like the framework is "ignoring" your configuration. It isn't. Your JSON is probably wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Keep one canonical configuration example in your repository. Test it. Validate important configuration through integration tests. And avoid turning &lt;code&gt;appsettings.json&lt;/code&gt; into an experimental art project. A known-good example is much easier to maintain than debugging configuration structure at 4pm on a Friday.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter Behavior Depends on Context Quality
&lt;/h2&gt;

&lt;p&gt;Percentage rollouts sound straightforward. Enable a feature for 20% of users. Easy. Except &lt;code&gt;PercentageFilter&lt;/code&gt; evaluates randomly, so the same user can potentially get different results across requests. That's fine for coarse rollouts. It's less fine when you expect a user to consistently see the same version of a feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;If you need stable per-user behavior, use &lt;code&gt;ConsistentPercentageFilter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In ASP.NET Core scenarios, it can use the current principal identity as a stable user key and assign that user to a deterministic bucket. The catch? Your context still matters. If the user identity is missing or changes between requests, the results can still look random. So before blaming the feature flag library, make sure you're actually giving it a consistent identity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Garbage context in. Confusing rollout behavior out.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;IsEnabledAsync&lt;/code&gt; Everywhere Means You Can Re-Evaluate a Lot
&lt;/h2&gt;

&lt;p&gt;Feature flag checks are asynchronous. They're also extremely easy to sprinkle throughout your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_featureManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FeatureFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDashboard&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Do something&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then somewhere deeper in the same request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_featureManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FeatureFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDashboard&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Do something else&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And again. And again. Before long, you're evaluating the same flag multiple times in one request path.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;When appropriate, evaluate the flag once and pass the result through the relevant operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;isNewDashboardEnabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_featureManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FeatureFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDashboard&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Use isNewDashboardEnabled throughout this operation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you clearer behavior and fewer opportunities for surprising changes between evaluations. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;IFeatureManager&lt;/code&gt; vs. &lt;code&gt;IFeatureManagerSnapshot&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You can inject either &lt;code&gt;IFeatureManager&lt;/code&gt; or &lt;code&gt;IFeatureManagerSnapshot&lt;/code&gt;. And the choice matters. For request-heavy applications, snapshot semantics are often what you actually want. &lt;code&gt;IFeatureManagerSnapshot&lt;/code&gt; provides consistency for the lifetime of a request or scope, so repeated checks can use the same evaluated state. That's useful when you don't want feature behavior changing halfway through an operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Prefer &lt;code&gt;IFeatureManagerSnapshot&lt;/code&gt; when consistent per-request behavior matters. Be intentional when using the non-snapshot manager. The important question isn't:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Which interface compiles?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They both do.&lt;/p&gt;

&lt;p&gt;The question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Could evaluating this flag differently during the same operation cause problems?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is yes, snapshot semantics are probably worth considering.&lt;/p&gt;

&lt;h2&gt;
  
  
  None of This Is a Dealbreaker
&lt;/h2&gt;

&lt;p&gt;Microsoft's feature management library is still a great default choice for .NET applications. Most of the pain comes from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Naming drift&lt;/li&gt;
&lt;li&gt;Configuration mistakes&lt;/li&gt;
&lt;li&gt;Context assumptions&lt;/li&gt;
&lt;li&gt;Repeated evaluations&lt;/li&gt;
&lt;li&gt;Not thinking about evaluation consistency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The framework is fine. Your future self just wants fewer typo-driven incidents. Add some guardrails, centralize your flag names, test your configuration, and understand how your filters and evaluation scope behave. Then you get the benefits of feature flags without quite as many mystery bugs.&lt;/p&gt;

&lt;p&gt;And if you're tired of managing flags through configuration files, &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt; gives you a central place to manage them without turning every flag change into an adventure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Know the quirks. Add the guardrails. Ship anyway.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>featureflags</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Cleaning Up Feature Flags: The Art of Not Leaving a Mess</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Thu, 20 Aug 2026 18:39:52 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/cleaning-up-feature-flags-the-art-of-not-leaving-a-mess-4ojl</link>
      <guid>https://dev.to/avlcodemonkey-industries/cleaning-up-feature-flags-the-art-of-not-leaving-a-mess-4ojl</guid>
      <description>&lt;p&gt;You said you'd remove that flag after launch. You lied. It's been six months and the flag is still in &lt;code&gt;appsettings.json&lt;/code&gt;, the &lt;code&gt;if&lt;/code&gt; statement is still in your controller, and nobody remembers which state is "on." This is how codebases turn into haunted houses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Cleanup Matters
&lt;/h2&gt;

&lt;p&gt;Dead feature flags are &lt;strong&gt;technical debt with teeth&lt;/strong&gt;. They add branches to your code that nobody tests. They confuse new developers who don't know the history. They inflate configuration files and make deployments harder to reason about. And they compound.&lt;/p&gt;

&lt;p&gt;Every flag you don't clean up makes the next cleanup harder because the cognitive load of understanding the system keeps increasing. The cost of removing a flag is lowest immediately after the feature ships, while everyone still remembers what the thing does. Six months later? Good luck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Track Every Flag
&lt;/h2&gt;

&lt;p&gt;You can't clean up what you can't find. Maintain a registry of every active feature flag with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name&lt;/li&gt;
&lt;li&gt;Purpose&lt;/li&gt;
&lt;li&gt;Owner&lt;/li&gt;
&lt;li&gt;Date created&lt;/li&gt;
&lt;li&gt;Expected removal date&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can be a spreadsheet, an issue tracker, internal documentation, or a dedicated feature flag management system. The format doesn't matter nearly as much as the habit. When you add a flag, add it to the registry. When you remove a flag, remove it from the registry. If your registry contains flags with no owner or no removal date, congratulations: you've found your next cleanup project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set Expiry Dates
&lt;/h2&gt;

&lt;p&gt;Every flag should have a planned removal date when it's created. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Release toggles:&lt;/strong&gt; Remove shortly after the feature ships. Two weeks is a reasonable default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experiment toggles:&lt;/strong&gt; Remove when the experiment concludes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ops toggles:&lt;/strong&gt; May be permanent by design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission toggles:&lt;/strong&gt; May also be permanent, but document that explicitly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a flag has been alive longer than its planned expiry and nobody deliberately extended it, it's already a zombie. Treat it accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make Cleanup Part of the Process
&lt;/h2&gt;

&lt;p&gt;Flag cleanup doesn't happen unless someone owns it. Add a cleanup step to your feature completion checklist. Better yet, create the cleanup ticket &lt;strong&gt;when you create the feature ticket&lt;/strong&gt;. The feature isn't done when it's released. It's done when the flag is gone.&lt;/p&gt;

&lt;p&gt;Some teams set automated alerts when flags exceed their planned lifetime. Others track flag counts on engineering dashboards. The specific mechanism doesn't matter much. Having a mechanism does.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Actually Remove a Flag
&lt;/h2&gt;

&lt;p&gt;Removing a flag isn't just deleting an &lt;code&gt;if&lt;/code&gt; statement. Here's the full checklist:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Determine which state the flag should permanently be in. Usually &lt;code&gt;enabled&lt;/code&gt; if the feature shipped successfully.&lt;/li&gt;
&lt;li&gt;Remove the flag check and keep the code from the permanent path.&lt;/li&gt;
&lt;li&gt;Delete the disabled code path completely. &lt;strong&gt;Don't comment it out.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Remove the flag definition from configuration and your flag management system.&lt;/li&gt;
&lt;li&gt;Update or remove tests that specifically covered the disabled state.&lt;/li&gt;
&lt;li&gt;Delete the flag from your registry.&lt;/li&gt;
&lt;li&gt;Deploy and verify.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 3 is where people get lazy. Commented-out code isn't deleted code. It's just code waiting to confuse someone six months from now. &lt;strong&gt;Delete it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal
&lt;/h2&gt;

&lt;p&gt;A well-maintained codebase has only the feature flags it actually needs. Each flag should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documented&lt;/li&gt;
&lt;li&gt;Owned&lt;/li&gt;
&lt;li&gt;Understandable&lt;/li&gt;
&lt;li&gt;Actively used&lt;/li&gt;
&lt;li&gt;Scheduled for removal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clean up isn't a one-time event. It's an ongoing engineering practice. Feature flags should make your system easier to operate, not turn it into an archaeological dig.&lt;/p&gt;

&lt;p&gt;If you want to make it easy to clean up your feature flags without editing configuration files in production, check out &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The only good zombie flag is a deleted one.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>technicaldebt</category>
      <category>codequality</category>
      <category>devops</category>
    </item>
    <item>
      <title>Feature Flags and Testing: Because QA Deserves Surprises Too</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Wed, 19 Aug 2026 17:59:43 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/feature-flags-and-testing-because-qa-deserves-surprises-too-2i0c</link>
      <guid>https://dev.to/avlcodemonkey-industries/feature-flags-and-testing-because-qa-deserves-surprises-too-2i0c</guid>
      <description>&lt;p&gt;Feature flags solve a lot of deployment problems. They also create a whole new set of testing problems. Every flag introduces a branch in your code. Every branch needs to be tested. The math gets uncomfortable fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State Explosion Problem
&lt;/h2&gt;

&lt;p&gt;One feature flag means two states: &lt;strong&gt;On. Off.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Two flags means four states. Ten flags means &lt;strong&gt;1,024 possible combinations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You are not going to test all of them. Nobody is. But some of those combinations will behave unexpectedly, and your users will find them at the worst possible time. The practical approach is to identify which flag combinations actually matter for your application and test those specifically.&lt;/p&gt;

&lt;p&gt;Flags that affect the same feature or code path are more likely to interact badly. Flags for completely independent features probably don't need to be tested together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Every State of Every Flag
&lt;/h2&gt;

&lt;p&gt;At a minimum, every flag should be tested in both its enabled and disabled states. This sounds obvious. It's also incredibly easy to forget. When adding a flag, developers tend to test the shiny new code path and forget to verify that the old path still works. Don't. Write explicit tests for both states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Index_ReturnsNewDashboard_WhenFlagEnabled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
    &lt;span class="n"&gt;_featureManager&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fm&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReturnsAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Act&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Assert&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;viewResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ViewResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Index_ReturnsOldDashboard_WhenFlagDisabled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
    &lt;span class="n"&gt;_featureManager&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fm&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReturnsAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Act&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Assert&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;viewResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ViewResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OldDashboard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both tests matter. &lt;strong&gt;Don't skip the disabled case.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's usually the code path everyone assumes will keep working forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the Flag Infrastructure
&lt;/h2&gt;

&lt;p&gt;Here's another fun question: &lt;strong&gt;What happens when your flag service is unavailable?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nobody's perfect. Your application should have a defined behavior when the flag infrastructure goes down. A safe default is usually to treat the flag as disabled. And yes, that behavior should be tested. "Works on my machine when the flag server is up" is not a test strategy.&lt;/p&gt;

&lt;p&gt;Write tests that simulate a flag service outage and verify that your application degrades gracefully. Users shouldn't see an error because a configuration service had a brief hiccup. The important part is that &lt;strong&gt;you know what happens and you've tested it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Automate Everything
&lt;/h2&gt;

&lt;p&gt;Manual testing of feature flag states doesn't scale. Have ten active flags? Asking QA to manually verify both states of every flag before every release is a fantastic way to produce burnout, missed coverage, and possibly a strongly worded email.&lt;/p&gt;

&lt;p&gt;Automate it. Your CI pipeline should run your flag-state tests automatically. Use mocks or test configuration to control flag values in your test suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't make your CI pipeline depend on a live flag server.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your tests should be deterministic. Your production infrastructure can provide enough chaos on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Document Expected Behavior
&lt;/h2&gt;

&lt;p&gt;For every flag, document what the application should do when the flag is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enabled&lt;/li&gt;
&lt;li&gt;Disabled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That documentation becomes the specification your tests enforce. Without documentation, "works on my machine" becomes the de facto specification. With documentation, everyone has a shared understanding of what correct behavior actually means. That makes it easier to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write tests&lt;/li&gt;
&lt;li&gt;Review code&lt;/li&gt;
&lt;li&gt;Diagnose bugs&lt;/li&gt;
&lt;li&gt;Understand old flags&lt;/li&gt;
&lt;li&gt;Remove flags safely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also makes explaining expected behavior to the person filing the bug report considerably easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Point
&lt;/h2&gt;

&lt;p&gt;Feature flags give you control. Testing makes sure that control doesn't turn into chaos. For every flag:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test the enabled state.&lt;/li&gt;
&lt;li&gt;Test the disabled state.&lt;/li&gt;
&lt;li&gt;Test important flag combinations.&lt;/li&gt;
&lt;li&gt;Test what happens when the flag infrastructure fails.&lt;/li&gt;
&lt;li&gt;Automate the tests in CI.&lt;/li&gt;
&lt;li&gt;Document the expected behavior.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And when the feature is fully released?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delete the flag.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fewer flags mean fewer states, fewer tests, and fewer opportunities for your codebase to develop a personality disorder.&lt;/p&gt;

&lt;p&gt;If you need a simple way to manage your feature flags without building your own flag infrastructure, check out &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test everything. Automate all of it. Document what you expect. Try not to cry.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>testing</category>
      <category>qa</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Implementing Feature Management in .NET: The Lazy Way</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Tue, 18 Aug 2026 18:57:53 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/implementing-feature-management-in-net-the-lazy-way-gcb</link>
      <guid>https://dev.to/avlcodemonkey-industries/implementing-feature-management-in-net-the-lazy-way-gcb</guid>
      <description>&lt;p&gt;Microsoft did the hard work so you don't have to.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Microsoft.FeatureManagement&lt;/code&gt; library integrates directly with .NET's configuration and dependency injection systems, which means you can get feature flags working with minimal code and a solid foundation. For the full documentation, check out the &lt;a href="https://learn.microsoft.com/en-us/azure/azure-app-configuration/feature-management-dotnet-reference" rel="noopener noreferrer"&gt;Microsoft Feature Management documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's get this thing running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Add the NuGet package to your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Microsoft.FeatureManagement.AspNetCore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it for dependencies. No magic rituals required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Register the feature management services in &lt;code&gt;Program.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFeatureManagement&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, feature flags are read from the &lt;code&gt;FeatureManagement&lt;/code&gt; section of your &lt;code&gt;appsettings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"FeatureManagement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ExperimentalSearch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flag names are strings. Values are booleans. Simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking a Flag in Code
&lt;/h2&gt;

&lt;p&gt;Inject &lt;code&gt;IFeatureManager&lt;/code&gt; wherever you need to check a flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IFeatureManager&lt;/span&gt; &lt;span class="n"&gt;_featureManager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DashboardController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IFeatureManager&lt;/span&gt; &lt;span class="n"&gt;featureManager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_featureManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;featureManager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_featureManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;View&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;View&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OldDashboard"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole pattern. &lt;strong&gt;Inject. Check. Branch. Repeat.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Feature Filters
&lt;/h2&gt;

&lt;p&gt;Boolean flags are useful, but sometimes you need something a little more sophisticated. The library supports feature filters for things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Percentage rollouts&lt;/li&gt;
&lt;li&gt;Time windows&lt;/li&gt;
&lt;li&gt;User targeting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, you can enable a feature for a percentage of requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"FeatureManagement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"BetaFeature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"EnabledFor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Percentage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables &lt;code&gt;BetaFeature&lt;/code&gt; for 20% of requests. The library handles the sampling. You handle the business logic. Everybody wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Razor Tag Helpers
&lt;/h2&gt;

&lt;p&gt;Building a Razor-based UI? The library includes a tag helper for conditionally rendering markup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;feature&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"new-dashboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/feature&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean, readable, and no C# in your markup. Some people consider this progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Way Is Often the Right Way
&lt;/h2&gt;

&lt;p&gt;Rolling your own feature flag system is a rite of passage. It's also probably not a good use of your time. Microsoft's library already handles the plumbing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;Dependency injection&lt;/li&gt;
&lt;li&gt;Feature filters&lt;/li&gt;
&lt;li&gt;Percentage rollouts&lt;/li&gt;
&lt;li&gt;Razor tag helpers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So you can focus on the actual feature instead of spending three days building a flag system that was supposed to take an afternoon. &lt;/p&gt;

&lt;p&gt;But there's one problem with the &lt;code&gt;appsettings.json&lt;/code&gt; approach:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Someone still has to edit the config file when you want to flip a flag.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And if that means changing configuration, committing it, deploying it, and waiting for the pipeline just to turn off a broken feature...&lt;/p&gt;

&lt;p&gt;You've basically recreated the problem feature flags were supposed to solve.&lt;/p&gt;

&lt;p&gt;A dedicated feature flag management UI lets you change flags without touching your configuration files or redeploying your application.&lt;/p&gt;

&lt;p&gt;That's where &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt; comes in.&lt;/p&gt;

&lt;p&gt;Why reinvent the wheel when someone already built the wheel factory?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be lazy. Ship more.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>featureflags</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Feature Flags and Continuous Delivery: Ship It Like You Mean It</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Mon, 17 Aug 2026 19:56:08 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/feature-flags-and-continuous-delivery-ship-it-like-you-mean-it-2hn6</link>
      <guid>https://dev.to/avlcodemonkey-industries/feature-flags-and-continuous-delivery-ship-it-like-you-mean-it-2hn6</guid>
      <description>&lt;p&gt;Continuous delivery means shipping code to production frequently — ideally on every merge to &lt;code&gt;main&lt;/code&gt;. Feature flags are what make that possible without turning every deployment into a high-stakes gamble.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Problem: Deployment vs. Release
&lt;/h2&gt;

&lt;p&gt;There's an important distinction that many teams blur:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploying code and releasing features are not the same thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deployment means putting code on a server. Release means making a feature visible to users. In a traditional workflow, these happen together. You deploy, and the feature immediately goes live. With feature flags, you can separate them. That's the foundation of continuous delivery:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy constantly. Release deliberately.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The feature flag controls when code goes from deployed to released. As Scott Hanselman puts it, feature flags let you separate deployment from release, giving you the power to experiment and react quickly. That's a pretty useful superpower.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test in Production (Carefully)
&lt;/h2&gt;

&lt;p&gt;Staging environments are valuable. They're also never quite the same as production. Real traffic patterns. Real data volumes. Real third-party integrations. Staging approximates these things, but it doesn't perfectly replicate them. &lt;/p&gt;

&lt;p&gt;Feature flags let you test in production in a controlled way. Enable a new feature for internal users only. Or expose it to a small percentage of real traffic. Then watch what happens.&lt;/p&gt;

&lt;p&gt;This isn't the same as shipping broken code to everyone and hoping for the best. It's a deliberate strategy for gathering production signal before committing to a full rollout. Your users become your test environment. Just... carefully.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instant Rollback Without a Redeployment
&lt;/h2&gt;

&lt;p&gt;Traditional rollbacks require reverting a deployment. That takes time, especially when your deployment pipeline has multiple steps, approvals, and enough YAML to qualify as a cry for help.&lt;/p&gt;

&lt;p&gt;With feature flags, rollback is just flipping a switch. If a newly released feature starts causing problems, disable it in seconds. The bad code is still in production, but it's no longer running. You've bought yourself time to investigate and fix the problem without immediately rolling back the entire deployment. Your weekend is now &lt;strong&gt;slightly&lt;/strong&gt; safer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trunk-Based Development
&lt;/h2&gt;

&lt;p&gt;Feature flags also make trunk-based development practical. Instead of maintaining long-lived feature branches, developers commit to the main branch frequently — often daily. But what happens when a feature isn't finished?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hide it behind a flag.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The incomplete code can be merged and deployed without exposing it to users. This means developers can integrate early and often instead of maintaining massive branches that eventually collide in a spectacular merge-conflict apocalypse.&lt;/p&gt;

&lt;p&gt;Trunk-based development can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce merge conflicts&lt;/li&gt;
&lt;li&gt;Improve integration quality&lt;/li&gt;
&lt;li&gt;Encourage smaller, more frequent deployments&lt;/li&gt;
&lt;li&gt;Simplify the delivery pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feature flags are the mechanism that makes unfinished work safe to deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Looks Like in Practice
&lt;/h2&gt;

&lt;p&gt;With feature flags and continuous delivery working together, your workflow might look something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up a flag management server so you're not editing &lt;code&gt;appsettings.json&lt;/code&gt; in production like an animal.&lt;/li&gt;
&lt;li&gt;Write the code. Wrap it in a flag. Merge to &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Deploy to production with the flag off.&lt;/li&gt;
&lt;li&gt;Enable the flag for internal users. Watch your metrics.&lt;/li&gt;
&lt;li&gt;Gradually roll it out to a wider audience.&lt;/li&gt;
&lt;li&gt;Fully release the feature.&lt;/li&gt;
&lt;li&gt;Remove the flag.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each step is reversible. Each step gives you more confidence. And if something goes wrong at any point, flip the flag and investigate. No emergency redeployment required.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Point
&lt;/h2&gt;

&lt;p&gt;Feature flags aren't just about turning features on and off. They're a key part of separating &lt;strong&gt;deployment from release&lt;/strong&gt;. That separation gives your team the freedom to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy frequently&lt;/li&gt;
&lt;li&gt;Test changes with real production traffic&lt;/li&gt;
&lt;li&gt;Roll out features gradually&lt;/li&gt;
&lt;li&gt;Disable broken functionality instantly&lt;/li&gt;
&lt;li&gt;Keep incomplete work off long-lived branches&lt;/li&gt;
&lt;li&gt;Practice continuous delivery without treating every deployment like a tripwire&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal isn't to eliminate risk. It's to make the risk &lt;strong&gt;manageable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you want to manage your feature flags without editing configuration files in production, check out &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ship constantly. Release deliberately. Sleep soundly.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>devops</category>
      <category>continuousdelivery</category>
      <category>deployment</category>
    </item>
    <item>
      <title>Feature Flag Pitfalls: How to Turn Your Codebase Into a Haunted House</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Mon, 17 Aug 2026 19:51:51 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/feature-flag-pitfalls-how-to-turn-your-codebase-into-a-haunted-house-1b1m</link>
      <guid>https://dev.to/avlcodemonkey-industries/feature-flag-pitfalls-how-to-turn-your-codebase-into-a-haunted-house-1b1m</guid>
      <description>&lt;p&gt;Feature flags are easy to add and hard to remove. That asymmetry is where the trouble starts.&lt;/p&gt;

&lt;p&gt;Used properly, feature flags give you safer deployments, gradual rollouts, and emergency kill switches. Used poorly, they turn your codebase into a &lt;strong&gt;haunted house full of dead branches nobody dares to touch.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here are some of the most common ways feature flags go wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zombie Flags
&lt;/h2&gt;

&lt;p&gt;A zombie flag is a flag that should have been deleted months ago but wasn't.&lt;/p&gt;

&lt;p&gt;The feature shipped. The experiment ended. Everyone moved on. But the flag?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Still there.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nobody remembers what it does, why it exists, or whether removing it will summon Cthulhu.&lt;/p&gt;

&lt;p&gt;Zombie flags accumulate over time. Eventually your codebase is full of &lt;code&gt;if&lt;/code&gt; statements that will never execute, conditions that are always true, and dead code paths nobody has tested in years.&lt;/p&gt;

&lt;p&gt;It's technical debt with extra steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;Treat flag cleanup as part of the feature work. When you create a flag, decide when it should go away. Put the removal task in the ticket. Assign an owner. Set a reminder. Do whatever it takes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't let flags outlive their purpose.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Flag Explosion
&lt;/h2&gt;

&lt;p&gt;One flag? Fine.&lt;/p&gt;

&lt;p&gt;Ten flags? Manageable.&lt;/p&gt;

&lt;p&gt;Fifty flags?&lt;/p&gt;

&lt;p&gt;Better start looking for that spreadsheet.&lt;/p&gt;

&lt;p&gt;A hundred flags?&lt;/p&gt;

&lt;p&gt;Congratulations. You have more feature flags than features.&lt;/p&gt;

&lt;p&gt;Flag explosion happens when teams add flags without a policy for removing them. Every new feature gets a flag "just in case," and somehow "just in case" becomes "forever."&lt;/p&gt;

&lt;p&gt;Now every deployment requires checking a giant configuration table before you can figure out what users are actually going to see.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;Keep track of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What each flag does&lt;/li&gt;
&lt;li&gt;Who owns it&lt;/li&gt;
&lt;li&gt;Why it exists&lt;/li&gt;
&lt;li&gt;When it should be removed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a flag has no owner and no expiration plan, it's already a zombie waiting to happen.&lt;/p&gt;

&lt;p&gt;Or, instead of maintaining yet another spreadsheet that everyone forgets exists, use a feature flag management tool that tracks this stuff for you.&lt;/p&gt;

&lt;p&gt;Because the spreadsheet you create at 2pm is definitely going to be updated when you're shipping at midnight.&lt;/p&gt;

&lt;p&gt;Right?&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Complexity
&lt;/h2&gt;

&lt;p&gt;Here's where feature flags get mathematically unpleasant.&lt;/p&gt;

&lt;p&gt;Every binary feature flag can double the number of possible states your application can be in.&lt;/p&gt;

&lt;p&gt;Two flags?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4 combinations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ten flags?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1,024 combinations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Twenty flags?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1,048,576 combinations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You probably don't have time to test all of those.&lt;/p&gt;

&lt;p&gt;Neither does your QA team.&lt;/p&gt;

&lt;p&gt;In practice, not every combination matters. But eventually you'll hit one that does, and you'll probably discover it when a user finds the exact combination you didn't test.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;Minimize the number of active flags.&lt;/p&gt;

&lt;p&gt;Retire old flags aggressively.&lt;/p&gt;

&lt;p&gt;Don't let temporary rollout flags become permanent application architecture.&lt;/p&gt;

&lt;p&gt;The longer a flag sticks around, the more combinations you have to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Missing Documentation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"What does &lt;code&gt;EnableSuperMode&lt;/code&gt; do?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"No idea. Don't touch it."&lt;/p&gt;

&lt;p&gt;This conversation happens at every company that uses feature flags without documenting them. The original developer left. The ticket was closed. The Slack thread disappeared into the void. And now everyone is terrified to remove the flag because &lt;strong&gt;nobody knows what happens when you flip it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every flag should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A name that explains what it does&lt;/li&gt;
&lt;li&gt;A description of why it exists&lt;/li&gt;
&lt;li&gt;An owner&lt;/li&gt;
&lt;li&gt;A plan for when it should be removed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can't explain a flag in one sentence, it's probably not ready to ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Feature flags are powerful. But power comes with responsibility, blah blah blah. The important part is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add them intentionally.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document them thoroughly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remove them ruthlessly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Feature flags should make your codebase easier to operate, not turn it into an archaeological dig.&lt;/p&gt;

&lt;p&gt;If you're managing more than a handful of flags, a dedicated flag management tool can help you keep track of what's active, who owns it, and what needs to be cleaned up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;Try FeatureFlags.app&lt;/a&gt; and stop letting your feature flags become zombies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The only good zombie flag is a deleted one.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>devops</category>
      <category>technicaldebt</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Feature Flags in the Real World: Use Cases That Won't Get You Fired</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Mon, 17 Aug 2026 19:48:33 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/feature-flags-in-the-real-world-use-cases-that-wont-get-you-fired-20j2</link>
      <guid>https://dev.to/avlcodemonkey-industries/feature-flags-in-the-real-world-use-cases-that-wont-get-you-fired-20j2</guid>
      <description>&lt;p&gt;Why do teams use feature flags?&lt;/p&gt;

&lt;p&gt;Because &lt;strong&gt;"move fast and break things"&lt;/strong&gt; is only fun until you break prod.&lt;/p&gt;

&lt;p&gt;Feature flags let you move fast and break things slightly less dramatically.&lt;/p&gt;

&lt;p&gt;Here’s how real engineering teams actually use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Canary Releases
&lt;/h2&gt;

&lt;p&gt;A canary release means you roll out a change to a small percentage of users first—say, 1%—before exposing it to everyone.&lt;/p&gt;

&lt;p&gt;If the 1% starts screaming, you flip the flag off and investigate.&lt;/p&gt;

&lt;p&gt;If they don't notice anything wrong, you gradually increase the rollout.&lt;/p&gt;

&lt;p&gt;The name comes from the old mining practice of bringing a canary into a coal mine to detect toxic gases.&lt;/p&gt;

&lt;p&gt;Your early users are the canary.&lt;/p&gt;

&lt;p&gt;Hopefully, nothing explodes.&lt;/p&gt;

&lt;p&gt;This pattern is especially valuable for high-traffic systems where even a small bug can affect thousands of users. Rolling out slowly gives you real production signal without betting the whole user base on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A/B Testing
&lt;/h2&gt;

&lt;p&gt;A/B testing with feature flags means showing two different versions of a feature to different groups of users and measuring which performs better.&lt;/p&gt;

&lt;p&gt;Want to know if the green button converts better than the blue one?&lt;/p&gt;

&lt;p&gt;Wrap it in a flag, split your traffic, and let the data decide.&lt;/p&gt;

&lt;p&gt;The flag controls group assignment. Your analytics platform measures the outcome.&lt;/p&gt;

&lt;p&gt;When the experiment concludes, you ship the winner and delete the flag.&lt;/p&gt;

&lt;p&gt;Simple in theory.&lt;/p&gt;

&lt;p&gt;Slightly painful in practice when the experiment runs for six months and everyone forgets what you were testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kill Switches
&lt;/h2&gt;

&lt;p&gt;Sometimes things go wrong in production.&lt;/p&gt;

&lt;p&gt;A third-party API starts returning garbage. A database query locks everything up. A new feature is causing unexplained memory leaks.&lt;/p&gt;

&lt;p&gt;You need to turn it off &lt;strong&gt;immediately&lt;/strong&gt;, without rolling back a deployment or waking up the release manager.&lt;/p&gt;

&lt;p&gt;That's where kill switches come in.&lt;/p&gt;

&lt;p&gt;Kill switches are ops-style feature flags that exist specifically for these moments. They're always off by default and flipped on only in emergencies.&lt;/p&gt;

&lt;p&gt;With a kill switch in place, the on-call engineer can disable a problematic feature in seconds rather than scrambling through a deployment pipeline at 2am.&lt;/p&gt;

&lt;p&gt;Your future, sleep-deprived self will thank you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beta Testing and Early Access
&lt;/h2&gt;

&lt;p&gt;Feature flags let you give specific users early access to new functionality before it's fully released.&lt;/p&gt;

&lt;p&gt;Power users. Internal testers. Customers in your beta program.&lt;/p&gt;

&lt;p&gt;Basically, anyone you trust to find bugs before the general public does.&lt;/p&gt;

&lt;p&gt;This lets you collect real feedback on a real feature without committing to a full release.&lt;/p&gt;

&lt;p&gt;If the feedback is bad, disable it for the beta group and go back to the drawing board.&lt;/p&gt;

&lt;p&gt;If the feedback is good, roll it out to everyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The flag controls access. Your users do the testing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Managing which users are in the beta group is a lot easier from a web UI than from a config file.&lt;/p&gt;

&lt;p&gt;A dedicated flag management tool can handle this without making you write custom targeting logic for every new beta cohort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dark Launches
&lt;/h2&gt;

&lt;p&gt;A dark launch means you run new code in production but don't show its output to users.&lt;/p&gt;

&lt;p&gt;You're testing performance and correctness under real load without making any user-visible change.&lt;/p&gt;

&lt;p&gt;The flag enables the code path. The results go to a log or metrics system instead of the UI.&lt;/p&gt;

&lt;p&gt;Dark launches are particularly useful for risky backend changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New database queries&lt;/li&gt;
&lt;li&gt;Algorithm replacements&lt;/li&gt;
&lt;li&gt;Infrastructure migrations&lt;/li&gt;
&lt;li&gt;Performance-sensitive changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get production-scale validation before committing to the new implementation.&lt;/p&gt;

&lt;p&gt;That's a much nicer way to discover that your clever new database query takes 45 seconds than discovering it after you've deployed it to 100% of your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Point
&lt;/h2&gt;

&lt;p&gt;Feature flags aren't just a fancy on/off switch.&lt;/p&gt;

&lt;p&gt;They're a way to &lt;strong&gt;separate deployment from release&lt;/strong&gt; and give your team more control over what happens after code reaches production.&lt;/p&gt;

&lt;p&gt;Use them for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Canary releases&lt;/li&gt;
&lt;li&gt;A/B testing&lt;/li&gt;
&lt;li&gt;Kill switches&lt;/li&gt;
&lt;li&gt;Beta and early access&lt;/li&gt;
&lt;li&gt;Dark launches&lt;/li&gt;
&lt;li&gt;Safer production rollouts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use feature flags.&lt;/p&gt;

&lt;p&gt;Break things more safely.&lt;/p&gt;

&lt;p&gt;Look like a genius when nothing goes wrong.&lt;/p&gt;

&lt;p&gt;And if you want a simple way to manage your flags without building your own admin UI, check out &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ship it.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>devops</category>
      <category>deployment</category>
      <category>testing</category>
    </item>
    <item>
      <title>Unlocking the Power of Feature Flags</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Mon, 17 Aug 2026 19:41:17 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/unlocking-the-power-of-feature-flags-1fg7</link>
      <guid>https://dev.to/avlcodemonkey-industries/unlocking-the-power-of-feature-flags-1fg7</guid>
      <description>&lt;p&gt;So, you shipped a new feature.&lt;/p&gt;

&lt;p&gt;Congrats! 🎉&lt;/p&gt;

&lt;p&gt;Now the app's acting weird.&lt;/p&gt;

&lt;p&gt;Do you nuke the whole release?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nah. Enter feature flags.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Feature Flags?
&lt;/h2&gt;

&lt;p&gt;Feature flags (aka feature toggles, aka &lt;strong&gt;"please don't break prod"&lt;/strong&gt;) let you flip features on or off without redeploying.&lt;/p&gt;

&lt;p&gt;It's like hiding switches all over your codebase, so you can turn stuff on for your favorite users—or just yourself, let's be honest—and turn it off when things inevitably go sideways.&lt;/p&gt;

&lt;p&gt;Martin Fowler calls feature flags:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"a powerful technique, allowing teams to modify system behavior without changing code."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Translation: &lt;strong&gt;you can break things more safely.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Feature Flags?
&lt;/h2&gt;

&lt;p&gt;Let's say you want to test a new feature, but only on Dave's machine because he's the only one who reads the docs.&lt;/p&gt;

&lt;p&gt;Or maybe you want to roll out a change slowly, just in case it's cursed.&lt;/p&gt;

&lt;p&gt;Feature flags let you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deploy Safely&lt;/strong&gt; — Ship code to production while keeping the scary stuff hidden.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A/B Test&lt;/strong&gt; — Show different features to different users and pretend you're doing science.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant Rollback&lt;/strong&gt; — Flip a switch and pretend nothing ever happened.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Delivery&lt;/strong&gt; — Ship all the time and break things less. In theory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As Scott Hanselman puts it, feature flags let you separate deployment from release, giving you the power to experiment and react quickly.&lt;/p&gt;

&lt;p&gt;That's a pretty useful superpower.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do Feature Flags Work?
&lt;/h2&gt;

&lt;p&gt;It's just a boolean, folks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On or off.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Store the flag in your code, a database, or some SaaS. Your application checks the flag before running the relevant code.&lt;/p&gt;

&lt;p&gt;You can make it as complicated as you want—user-specific, time-based, or tied to the phase of the moon.&lt;/p&gt;

&lt;p&gt;Here's a basic example in C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_featureManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;View&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewDashboard"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;View&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OldDashboard"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple enough.&lt;/p&gt;

&lt;p&gt;But if editing &lt;code&gt;appsettings.json&lt;/code&gt; every time you want to flip a flag sounds like a bad time, you're not wrong.&lt;/p&gt;

&lt;p&gt;A central flag management server with a proper web UI is the better move:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No config file edits&lt;/li&gt;
&lt;li&gt;No redeployments&lt;/li&gt;
&lt;li&gt;No waiting for CI/CD&lt;/li&gt;
&lt;li&gt;Just a switch you can flip from a browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're impatient, &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt; is free to try.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code Monkey's Caution
&lt;/h2&gt;

&lt;p&gt;With great power comes great spaghetti.&lt;/p&gt;

&lt;p&gt;Too many flags and your codebase becomes a haunted house.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Label your flags. Document them. Delete them when you're done.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You won't.&lt;/p&gt;

&lt;p&gt;But you should.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Feature flags help you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ship safely&lt;/li&gt;
&lt;li&gt;Experiment with new functionality&lt;/li&gt;
&lt;li&gt;Roll out changes gradually&lt;/li&gt;
&lt;li&gt;Turn off broken features without a redeploy&lt;/li&gt;
&lt;li&gt;Separate deployment from release&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use them wisely, and maybe you'll survive your next production release.&lt;/p&gt;

&lt;p&gt;And if you want a simple way to manage your flags without wrestling with config files, give &lt;a href="https://featureflags.app/" rel="noopener noreferrer"&gt;FeatureFlags.app&lt;/a&gt; a try.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case closed. For now. Go get coffee.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>devops</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Fear Is the Mind-Killer. Dependencies Are the Build-Killer</title>
      <dc:creator>AvlCodeMonkey</dc:creator>
      <pubDate>Tue, 11 Aug 2026 16:02:38 +0000</pubDate>
      <link>https://dev.to/avlcodemonkey-industries/fear-is-the-mind-killer-dependencies-are-the-build-killer-32cl</link>
      <guid>https://dev.to/avlcodemonkey-industries/fear-is-the-mind-killer-dependencies-are-the-build-killer-32cl</guid>
      <description>&lt;p&gt;Remember when adding a package was just:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install some-random-thing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What could possibly go wrong? Well... &lt;strong&gt;Shai-Hulud&lt;/strong&gt; happened. The recent Shai-Hulud supply-chain attacks are a particularly nasty reminder that every dependency is an invitation into your build environment. Those attacks compromised legitimate packages and used stolen credentials to spread to other packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  He Who Controls the Dependencies Controls the Build
&lt;/h2&gt;

&lt;p&gt;Every dependency adds more code to trust, more vulnerabilities to monitor, and more updates to manage. This doesn't mean "never use dependencies" or "always re-invent the wheel". We'd all still be writing our own HTTP clients and arguing about JSON parsers. It means &lt;strong&gt;minimize them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you do need a dependency, consider who maintains it and how much trust you're giving it. For .NET developers, something like Microsoft's &lt;code&gt;Microsoft.FeatureManagement&lt;/code&gt; is a very different proposition from grabbing an obscure package maintained by someone with an unpronounceable alias. Microsoft isn't magically immune to vulnerabilities. No one is. But established vendors with mature security practices, release processes, and large communities can be a more comfortable place to put your trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Spice Must Flow. Your Dependencies Don't Have To
&lt;/h2&gt;

&lt;p&gt;Don't blindly consume &lt;code&gt;latest&lt;/code&gt;. Pin dependencies to specific versions. Keep lock files under source control. Update deliberately. Review dependency changes instead of letting the package manager summon whatever happens to be waiting in the desert.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Remove dependencies you don't actually need.&lt;/li&gt;
&lt;li&gt;  Audit direct &lt;strong&gt;and transitive&lt;/strong&gt; dependencies.&lt;/li&gt;
&lt;li&gt;  Monitor for known vulnerabilities.&lt;/li&gt;
&lt;li&gt;  Use trusted package sources.&lt;/li&gt;
&lt;li&gt;  Verify package provenance and signatures where available.&lt;/li&gt;
&lt;li&gt;  Keep CI/CD credentials locked down.&lt;/li&gt;
&lt;li&gt;  Give build processes only the permissions they actually need.&lt;/li&gt;
&lt;li&gt;  Treat unexpected dependency updates as something worth investigating.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Yes, We're a Dependency Too
&lt;/h2&gt;

&lt;p&gt;FeatureFlags.app is a third-party dependency. We know. The irony is not lost on us. That's why the client library is intentionally small and open source. You can inspect it yourself - &lt;strong&gt;&lt;a href="https://github.com/AvlCodeMonkey-Industries/FeatureFlags.Client" rel="noopener noreferrer"&gt;FeatureFlags.Client on GitHub&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal isn't to eliminate every dependency. The goal is to understand what you're trusting and keep that trust as small as practical.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Walk without rhythm and maybe the worm won't find you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dependencies</category>
      <category>supplychain</category>
      <category>security</category>
      <category>featureflags</category>
    </item>
  </channel>
</rss>
