FeaturOne 1.0.0

dotnet add package FeaturOne --version 1.0.0
                    
NuGet\Install-Package FeaturOne -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FeaturOne" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FeaturOne" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="FeaturOne" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FeaturOne --version 1.0.0
                    
#r "nuget: FeaturOne, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FeaturOne@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FeaturOne&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=FeaturOne&version=1.0.0
                    
Install as a Cake Tool

FeaturOne

Internal feature flags for .NET applications: a SQL table as the source of truth, overlays from appsettings.json and environment variables, plus sticky canary rollouts.

The package is evaluation-only. Applications create the table, manage rows themselves, and call IFeatureFlagService.IsEnabled.

Install

dotnet add package FeaturOne

Then run the script that matches your database (also packed under scripts/ in the NuGet package):

Configuration

Add a FeatureFlags section. ASP.NET Core already applies environment variables on top of JSON, so FeatureFlags__Flags__NewCheckout__Enabled=true wins over appsettings.json.

{
  "FeatureFlags": {
    "ConnectionString": "Server=.;Database=App;Trusted_Connection=True;TrustServerCertificate=True;",
    "TableName": "FeatureFlags",
    "SqlDialect": "SqlServer",
    "RefreshInterval": "00:00:30",
    "Flags": {
      "NewCheckout": {
        "Enabled": true,
        "RolloutMode": "Canary",
        "CanaryStartAt": "2026-08-18T00:00:00Z",
        "CanaryDuration": "1.00:00:00",
        "PinProperty": "user.id"
      },
      "LegacyReport": {
        "Enabled": false
      }
    }
  }
}

CanaryDuration uses .NET TimeSpan text (1.00:00:00 = 24 hours).

Precedence (per property)

  1. Environment variables
  2. appsettings.json (FeatureFlags:Flags:<name>)
  3. FeatureFlags table

A flag may exist only in configuration. If the database is unreachable, FeaturOne keeps the last successful table snapshot, applies configuration on top, and logs a warning. An unknown flag is off.

Registration

The package does not take a SQL provider dependency. The host supplies a connection factory:

builder.Services.AddFeaturOne(builder.Configuration, options =>
{
    options.ConnectionFactory = () => new SqlConnection(options.ConnectionString);
    // options.SqlDialect = FeaturOneSqlDialect.PostgreSql;
});

Without ConnectionFactory, only configuration and environment flags are evaluated.

Evaluation

public sealed class CheckoutService(IFeatureFlagService flags)
{
    public async Task<IResult> HandleAsync(User user)
    {
        var context = new FeatureContext
        {
            ["user.id"] = user.Id.ToString()
        };

        if (await flags.IsEnabledAsync("NewCheckout", context))
        {
            return Results.Ok("canary path");
        }

        return Results.Ok("stable path");
    }
}

Instant flags do not need a context. Canary flags fail closed when PinProperty is missing on the flag or the value is missing from FeatureContext.

States and rollout

Enabled RolloutMode Result
false any Always off
true Instant Always on
true Canary Linear ramp from 0% to 100% between CanaryStartAt and CanaryStartAt + CanaryDuration

Before the start instant the canary is 0%. After the window it is 100%.

Sticky pinning

The bucket is SHA256(flagName + pinProperty + pinValue) mapped to 0..9999. The same subject stays in the same bucket for the life of the flag. As the percentage increases the included set is monotonic: once a subject is in, it stays in.

PinProperty is configurable per flag (user.id, tournament.code, …). Use that exact key in FeatureContext.

Table

Column Meaning
Name Primary key
Enabled Master switch
RolloutMode Instant or Canary
CanaryStartAt Ramp start (UTC)
CanaryDuration .NET TimeSpan text
PinProperty Context key used for pinning
UpdatedAt Audit only, not read by the package

TableName must be a simple identifier (FeatureFlags, not dbo.FeatureFlags). Set the default schema on the connection or use a synonym if you need a different schema.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 251 8/18/2026