Skip to content
Go back

Feature Flags - What and Why

Published:

What are feature flags? Why should you use them?

Firstly, what are they? Feature flags are a method of being able to enable and disable features in an application without having to redeploy your application. They can be used for simple features like displaying content or not, or they can be used for more complex features such as enabling or disabling an AI help chat.

Secondly, why should you use them? The main reason is being able to disable a feature without having to redeploy your application, which would potentially cause downtime. This could be needing to disable it because it doesn’t work, or because you weren’t ready to release it. This last part is incredibly beneficial in my opinion. If you are working in an agile way you want to be completing PRs as soon as they are done, and that means code is into the main branch. But what if that feature isn’t fully ready or tested, well without feature flags you’d be stuck not able to release from that branch. Using flagging you can just disable that feature and keep up a steady release cycle.

For example, I recently implemented feature flagging in a Blazor project I was helping with. We needed to be able to publish to all of our environments, critically production, but in production we could only show a holding page for the time being. This was previously implemented in a separate branch and the deployment pipeline run from that branch. Instead, we now have a simple feature flag that changes what pages are rendered to enable this control.

How to implement feature flags

There are several ways to implement feature flags, from simple boolean checks with config values to using a third-party service. The way you implement depends on a number of things including the team, infrastructure, and the budget.

Simple Boolean Checks

The simplest way to implement feature flags is to use a boolean check in your code. This can be done by using a configuration file or environment variable to store the flag state.

if (Configuration["FeatureFlags:NewFeature"] == "true")
{
    // Execute new feature code
}
else
{
    // Execute old feature code
}

Pretty simple, right? And this can be repeated anywhere, especially if you use dependency injection to inject the configuration into the rest of the codebase. It does have its drawbacks though. Firstly, you would have to have access to the hosting environment to change the configuration value, for example access to the Azure App Service hosting it. Secondly, if you are using Azure App Service, these values are held as environment variables, and changing them causes the application to restart. This means we lose out on the benefit of not having to cause any downtime.

Azure App Configuration

Okay, so as an Azure Architect, I am obviously going to have a bias to Azure options and therefore have to mention App Configuration. This is a really well-priced service within Azure which can be used with a number of different SDKs and application types. One of the key benefits is that it can watch for config changes and update without having to restart the application.

builder.Services.AddAzureAppConfiguration();

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    var settings = config.Build();
    config.AddAzureAppConfiguration(options =>
    {
        options.Connect(settings["ConnectionStrings:AppConfig"])
               .UseFeatureFlags()
               .ConfigureRefresh(refreshOptions =>
               {
                   refreshOptions.Register("FeatureFlags:Sentinel", refreshAll: true)
                                 .SetCacheExpiration(TimeSpan.FromSeconds(30));
               });
    });
});

// Add feature management
builder.Services.AddFeatureManagement();

A really powerful tool which has a built-in feature flag system which can be simply enabled. You can then add a feature gate to the code, for example in a controller:

using Microsoft.AspNetCore.Mvc;
using Microsoft.FeatureManagement;

namespace MyApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class BetaController : ControllerBase
    {
        private readonly IFeatureManager _featureManager;

        public BetaController(IFeatureManager featureManager)
        {
            _featureManager = featureManager;
        }

        [HttpGet]
        public async Task<IActionResult> Get()
        {
            if (await _featureManager.IsEnabledAsync("CoolNewFeature"))
            {
                return Ok(new { message = "Beta feature is ENABLED" });
            }

            return NotFound(new { message = "Beta feature is DISABLED" });
        }
    }
}

As you can see in the example, the get method will only respond with an OK if the feature is enabled in App Configuration.

Using Azure App Configuration is perfect if you are already using Azure services. It allows you to make these configuration changes without having to restart the application. It also allows your platform team to limit the access that people need to be able to change these. Instead of a user having to have contributor rights on the whole App Service, they can just be given rights on the App Configuration. Yes, there is still a risk of malicious activity this way, but the blast radius is smaller.

Third Party Services

There are several third-party services that can be used to manage and implement feature flags. Using a more platform-agnostic service can be beneficial, especially if you are multi-cloud, or still hosting on-premises. These services would allow you to use the same management pane and implementation regardless of the hosting environment. They do come with additional costs which would need to be factored into any pricing for a project.

One popular option is LaunchDarkly 🔗. I won’t go into detail about how to implement this as it’s well documented on their site, for example for .NET here 🔗. Something I do like about LaunchDarkly is the really clean and simple UI that is provided for managing the flags. I can see this as being great for being able to delegate the control of the flags to a wider team, such as product owners.

Summary

Whilst I have not been in a position personally to use a service such as LaunchDarkly, I can definitely see the benefits of using an independent service like this. You get all of the flexibility but with a wider range of supported environments. Now, that isn’t to say you couldn’t, for example, use Azure App Configuration with an application hosted on-premises, but would you be paying for Azure if you are hosting on-premises?

Implementing feature flags is a must-have in my opinion for any project, especially one working in an agile way. No matter how you choose to implement them, they will be beneficial to the application. Yes, there is some additional work upfront to set it up, and you have to make sure they are implemented for each feature needing one, but the benefits far outweigh the costs.


Share this post on:

Previous Post
Sharing Code Across .NET Projects with csproj Includes: An Azure Functions Example
Next Post
Troubleshooting Entra External Identities B2C OTP Emails