Feature Flags in .NET and How I Use Them for A/B Testing
Tags: aspnetcore, featureflags, splittesting, abtesting
Published: 2023-10-14 10:51:29

---
title: Feature Flags in .NET and How I Use Them for A/B Testing
published: true
date: 2023-09-16 00:00:00 UTC
tags: aspnetcore,featureflags,splittesting,abtesting
canonical_url: https://www.milanjovanovic.tech/blog/feature-flags-in-dotnet-and-how-i-use-them-for-ab-testing
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2y366w6p9lfr9dete68.png
---
The ability to conditionally turn features on or off in your application without redeploying the code is a powerful tool.

It lets you quickly iterate on new features and frequently integrate your changes with the main branch.

You can use **feature flags** to achieve this.

**Feature flags** are a software development technique that allows you to wrap application features in a conditional statement. You can then toggle the feature on or off in runtime to control which features are enabled.

We have a lot to cover in this week's newsletter:

- Feature flag fundamentals in .NET
- Feature filters and phased rollouts
- Trunk-based development
- A/B testing

Let's dive in!

## Feature Flags In .NET

[Feature flags](https://github.com/microsoft/FeatureManagement-Dotnet) provide a way for .NET and ASP.NET Core applications to turn features on or off dynamically.

To get started, you need to install the `Microsoft.FeatureManagement` library in your project:

```csharp
Install-Package Microsoft.FeatureManagement
```

This library will allow you to develop and expose application functionality based on features. It's useful when you have special requirements when a new feature should be enabled and under what conditions.

The next step is to register the required services with dependency injection by calling `AddFeatureManagement`:

```csharp
builder.Services.AddFeatureManagement();
```

And you are ready to create your first feature flag. Feature flags are built on top of the .NET configuration system. Any .NET configuration provider can act as the backbone for exposing feature flags.

Let's create a feature flag called `ClipArticleContent` in our `appsettings.json` file:

```json
"FeatureManagement": {
  "ClipArticleContent": false
}
```

By convention, feature flags have to be defined in the `FeatureManagement` configuration section. But you can change this by providing a different configuration section when calling `AddFeatureManagement`.

Microsoft recommends exposing feature flags using enums and then consuming them with the `nameof` operator. For example, you would write `nameof(FeatureFlags.ClipArticleContent)`.

However, I prefer defining feature flags as constants in a static class because it simplifies the usage.

```csharp
// Using enums
public enum FeatureFlags
{
    ClipArticleContent = 1
}

// Using constants
public static class FeatureFlags
{
    public const string ClipArticleContent = "ClipArticleContent";
}
```

To check the feature flag state, you can use the `IFeatureManager` service. In this example, if the `ClipArticleContent` feature flag is turned on, we will return only the first thirty characters of the article's content.

```csharp
app.MapGet("articles/{id}", async (
    Guid id,
    IGetArticle query,
    IFeatureManager featureManager) =>
{
    var article = query.Execute(id);

    if (await featureManager.IsEnabledAsync(FeatureFlags.ClipArticleContent))
    {
        article.Content = article.Content.Substring(0, 50);
    }

    return Results.Ok(article);
});
```

You can also apply feature flags on a controller or endpoint level using the `FeatureGate` attribute:

```csharp
[FeatureGate(FeatureFlags.EnableArticlesApi)]
public class ArticlesController : Controller
{
   // ...
}
```

This covers the fundamentals of using feature flags, and now, let's tackle more advanced topics.

## Feature Filters And Phased Rollouts

The feature flags I showed you in the previous section were like a simple on-off switch. Although practical, you might want more flexibility from your feature flags.

The `Microsoft.FeatureManagement` package comes with a few built-in feature filters that allow you to create dynamic rules for enabling feature flags.

The available feature filters are[`Microsoft.Percentage`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.featuremanagement.featurefilters.percentagefilter?view=azure-dotnet),[`Microsoft.TimeWindow`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.featuremanagement.featurefilters.timewindowfilter?view=azure-dotnet)and [`Microsoft.Targeting`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.featuremanagement.featurefilters.targetingfilter?view=azure-dotnet).

Here's an example of defining a `ShowArticlePreview` feature flag that uses a percentage filter:

```json
"FeatureFlags": {
  "ClipArticleContent": false,
  "ShowArticlePreview": {
    "EnabledFor": [
      {
        "Name": "Percentage",
        "Parameters": {
          "Value": 50
        }
      }
    ]
  }
}
```

This means the feature flag will be randomly turned on 50% of the time. The downside is the same user might see different behavior on subsequent requests. A more realistic scenario is to have the feature flag state be cached for the duration of the user's session.

To use the `PercentageFilter`, you need to enable it by calling `AddFeatureFilter`:

```csharp
builder.Services.AddFeatureManagement().AddFeatureFilter<PercentageFilter>();
```

Another interesting feature filter is the `TargetingFilter`, which allows you to target specific users. Targeting is used in phased rollouts, where you want to introduce a new feature to your users gradually. You start by enabling the feature for a small percentage of users and slowly increase the rollout percentage while monitoring how the system responds.

## Trunk-based Development and Feature Flags

[Trunk-based development](https://trunkbaseddevelopment.com/) is a Git branching strategy where all developers work in short-lived branches or directly in the trunk, the main codebase. The _"trunk"_ is the main branch of your repository. If you're using Git, it will be either the `main` or `master` branch. Trunk-based development avoids the "merge hell" problem caused by long-lived branches.

So, how do feature flags fit into trunk-based development?

The only way to ensure the trunk is always releasable is to hide incomplete features behind feature flags. You continue pushing changes to the trunk as you work on the feature while the feature flag remains turned off on the main branch. When the feature is complete, you turn on the feature flag and release it to production.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uedc9djoswegm9zs2991.png)

## How I Used Feature Flags for A/B Testing On My Website

A/B testing (split testing) is an experiment where two or more variants of a page (or feature) are shown randomly to users. Statistical analysis is performed in the background to determine which variation performs better for a given conversion goal.

Here's an example A/B test I performed on my website:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4srx0v5rak3aspscrdgq.png)

The hypothesis was that removing the image and focusing on the benefits would make more people want to subscribe. I measure this using the conversion rate, which is the number of people visiting the page divided by the number of people subscribing.

I'm using a platform called [Posthog](https://posthog.com) to run experiments, which automatically calculates the results.

You can see that the _test_ variant has a significantly higher conversion rate, so it becomes the winner of the A/B test.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/izx1k2n2nsimw8l83ziw.png)

## Takeaway

The ability to dynamically turn features on or off without deploying the code is like a superpower. Feature flags give you this ability with very little work.

You can work with feature flags in .NET by installing the `Microsoft.FeatureManagement` library. Feature flags build on top of the .NET configuration system, and you can check the feature flag state using the `IFeatureManager` service.

Another use case for feature flags is A/B testing. I run weekly experiments on my website, testing changes that will improve my conversion rate. Feature flags help me decide which version of the website to show to the user. And then, I can measure results based on the user's actions.

I also made a video about [**feature flagging in .NET,**](https://youtu.be/QVEUgIC7Wpo) and you can watch it [**here**](https://youtu.be/QVEUgIC7Wpo) if you want to learn more.

Hope this was valuable.

Stay awesome!

* * *

**P.S. Whenever you're ready, there are 2 ways I can help you:**

1. [**Pragmatic Clean Architecture:**](https://www.milanjovanovic.tech/pragmatic-clean-architecture?utm_source=dev.to&utm_medium=website&utm_campaign=cross-posting) This comprehensive course will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture. [**Join 1,000+ students here.**](https://www.milanjovanovic.tech/pragmatic-clean-architecture?utm_source=dev.to&utm_medium=website&utm_campaign=cross-posting)

2. [**Patreon Community:**](https://www.patreon.com/milanjovanovic) Think like a senior software engineer with **access to the source code** I use in my YouTube videos and **exclusive discounts** for my courses. [**Join 860+ engineers here.**](https://www.patreon.com/milanjovanovic)