A sample Azure Functions application demonstrating Feature Management with Microsoft Feature Flags, including percentage-based feature rollouts and user targeting.
This project showcases how to implement feature flags in Azure Functions using:
- Microsoft.FeatureManagement for feature flag management
- Percentage Filter for gradual rollouts
- Targeting Filter for user-specific feature control
- .NET 8 as the target framework
FeatureFlags.Sample/ ├── Functions/ │ └── BetaFeatureFunction.cs # Main HTTP trigger function ├── appsettings.json # Feature flag configuration ├── local.settings.json # Local development settings ├── host.json # Azure Functions host configuration ├── Startup.cs # Dependency injection setup └── GlobalUsings.cs # Global using statements
- .NET 8 SDK
- Azure Functions Core Tools
- Azurite or Azure Storage Account
The local.settings.json file contains essential configuration for local development:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_INPROC_NET8_ENABLED": "1",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
| Setting | Value | Description |
|---|---|---|
IsEncrypted |
false |
Indicates if the settings values are encrypted (typically false for local development) |
AzureWebJobsStorage |
UseDevelopmentStorage=true |
Uses Azurite storage emulator for local development. For production, use actual Azure Storage connection string |
FUNCTIONS_INPROC_NET8_ENABLED |
1 |
Enables .NET 8 in-process hosting model for Azure Functions |
FUNCTIONS_WORKER_RUNTIME |
dotnet |
Specifies the language runtime for Azure Functions |
You can extend local.settings.json with additional settings as needed:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_INPROC_NET8_ENABLED": "1",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"APPINSIGHTS_INSTRUMENTATIONKEY": "your-app-insights-key",
"AZURE_CLIENT_ID": "your-client-id",
"AZURE_CLIENT_SECRET": "your-client-secret"
}
}
- Start Azurite (if using local storage emulator):azurite --silent --location c:\azurite --debug c:\azurite\debug.log
- Run the Functions app:cd FeatureFlags.Sample func start
- Test the endpoint:# Test without userId (generates random user) curl http://localhost:7071/api/BetaFeatureFunction
curl "http://localhost:7071/api/BetaFeatureFunction?userId=user1@example.com"
Feature flags are configured in appsettings.json:
{
"FeatureManagement": {
"BetaFeature": {
"EnabledFor": [
{
"Name": "Microsoft.Percentage",
"Parameters": {
"Value": 20
}
}
]
}
}
}
This configuration enables the BetaFeature for 20% of users based on a consistent hash of their user ID.
Tests whether a user has access to the beta feature.
Query Parameters:
userId(optional): User identifier for targeting. If not provided, a random GUID is generated.
Response:{ "userId": "user1@example.com", "hasAccess": true, "bucket": 15, "message": "✅ User 'user1@example.com' has access to BetaFeature (bucket: 15)." }
The project includes comprehensive unit tests in FeatureFlags.Sample.Test that validate:
- Feature flag evaluation with and without user IDs
- Percentage distribution accuracy
- Bucket calculation consistency
- Various percentage scenarios (0%, 50%, 100%)
Run tests with:dotnet test
For deployment to Azure:
- Update
local.settings.jsonvalues as Azure Function App Configuration settings - Replace
UseDevelopmentStorage=truewith actual Azure Storage connection string - Configure Application Insights if needed
- Deploy using Azure CLI, GitHub Actions, or Visual Studio
local.settings.jsonis automatically excluded from source control via.gitignore- Never commit sensitive connection strings or secrets to version control
- Use Azure Key Vault for production secrets
- The
CopyToPublishDirectoryis set toNeverforlocal.settings.jsonin the project file
- Microsoft.Azure.Functions.Extensions - Dependency injection for Azure Functions
- Microsoft.Azure.WebJobs.Extensions.OpenApi - OpenAPI/Swagger support
- Microsoft.FeatureManagement - Feature flag management
- Microsoft.NET.Sdk.Functions - Azure Functions SDK for .NET