Skip to content

Azure App Configuration in ConnectSoft Microservice Template

Purpose & Overview

Azure App Configuration is a managed service that provides centralized configuration management for microservices. In the ConnectSoft Microservice Template, Azure App Configuration serves as an optional configuration provider that enables dynamic configuration updates, feature flag management, and centralized configuration storage without requiring application redeployment.

Why Azure App Configuration?

Azure App Configuration offers several key benefits:

  • Centralized Management: Single source of truth for configuration across multiple services
  • Dynamic Updates: Change configuration without redeploying applications
  • Environment Support: Use labels to manage environment-specific configurations
  • Feature Flags: Built-in feature flag management and rollout
  • Security: Integration with Azure Key Vault for secrets management
  • Governance: Role-based access control, audit logs, and versioning
  • Performance: Efficient polling and caching with minimal overhead
  • Scalability: Supports thousands of configuration keys and values

Azure App Configuration Philosophy

Azure App Configuration provides a centralized, secure, and scalable way to manage application configuration and feature flags. It enables teams to update configuration in real-time without code changes, supports multi-environment deployments, and integrates seamlessly with Azure Key Vault for secure secret management.

Architecture Overview

Azure App Configuration Position in Configuration Hierarchy

Command-Line Arguments (Highest Priority)
Environment Variables
Azure App Configuration (if enabled)
    ├── Configuration Keys
    ├── Feature Flags
    └── Key Vault References
appsettings.{Environment}.json
appsettings.json (Base)

Configuration Flow

Azure App Configuration Store
    ├── Configuration Keys/Values
    ├── Feature Flags
    └── Key Vault References
AddAzureAppConfiguration()
    ├── Key Selection (.Select)
    ├── Refresh Configuration (.ConfigureRefresh)
    ├── Feature Flags (.UseFeatureFlags)
    └── Client Options (.ConfigureClientOptions)
IConfiguration
Options Pattern
    ├── IOptions<T> (Immutable)
    ├── IOptionsSnapshot<T> (Scoped, Reloadable)
    └── IOptionsMonitor<T> (Singleton, Reloadable)
UseAzureAppConfiguration() Middleware
    └── Dynamic Refresh Polling

Service Registration

Configuration Setup

Azure App Configuration is registered in Program.cs:

// Program.cs
private static void DefineConfiguration(
    string[] args, 
    HostBuilderContext hostBuilderContext, 
    IConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Sources.Clear();
    configurationBuilder
        .SetBasePath(hostBuilderContext.HostingEnvironment.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile(
            $"appsettings.{hostBuilderContext.HostingEnvironment.EnvironmentName}.json",
            optional: true,
            reloadOnChange: true);

#if UseAzureAppConfigurationAsAdditionalConfigurationProvider
    // Build configuration to get connection string
    IConfigurationRoot configurationRoot = configurationBuilder.Build();

    // Use dynamic configuration in an ASP.NET Core app
    // https://learn.microsoft.com/en-us/azure/azure-app-configuration/enable-dynamic-configuration-aspnet-core
    configurationBuilder.AddAzureAppConfiguration(options =>
    {
        string? azureAppConfigurationConnectionString = 
            configurationRoot.GetConnectionString("AzureAppConfiguration");

        options.Connect(azureAppConfigurationConnectionString)

            // Load all keys that start with ConnectSoft.MicroserviceTemplate: and have no label
            .Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null)

            // Configure to reload configuration if the registered sentinel key is modified
            .ConfigureRefresh(refresh =>
            {
                refresh.Register(
                    "ConnectSoft.MicroserviceTemplate:Settings:Sentinel", 
                    refreshAll: true);
                refresh.SetRefreshInterval(TimeSpan.FromMinutes(30));
            })

            // Configure client retry options
            .ConfigureClientOptions(options =>
            {
                options.Retry.MaxRetries = 1;
            });

#if UseAzureAppConfigurationAsFeatureFlagsProvider
        // Configure feature flags
        options.UseFeatureFlags(featureFlagsOptions =>
        {
            featureFlagsOptions.Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null);
            featureFlagsOptions.SetRefreshInterval(TimeSpan.FromMinutes(30));
        });
#endif
    });
#endif

    configurationBuilder
        .AddEnvironmentVariables()
        .AddCommandLine(args);
}

Service Registration Extension

// AzureAppConfigurationExtensions.cs
internal static IServiceCollection AddMicroserviceAzureAppConfiguration(
    this IServiceCollection services)
{
    ArgumentNullException.ThrowIfNull(services);

    services.AddAzureAppConfiguration();

    return services;
}

Registration:

// MicroserviceRegistrationExtensions.cs
#if UseAzureAppConfigurationAsAdditionalConfigurationProvider
    services.AddMicroserviceAzureAppConfiguration();
#endif

Middleware Registration

// AzureAppConfigurationExtensions.cs
internal static IApplicationBuilder UseMicroserviceAzureAppConfiguration(
    this IApplicationBuilder app)
{
    ArgumentNullException.ThrowIfNull(app);

    app.UseAzureAppConfiguration();

    return app;
}

Middleware Pipeline:

// MicroserviceRegistrationExtensions.cs
#if UseAzureAppConfigurationAsAdditionalConfigurationProvider
    application.UseMicroserviceAzureAppConfiguration();
#endif

Configuration

Connection String

appsettings.json:

{
  "ConnectionStrings": {
    "AzureAppConfiguration": "Endpoint=https://{store}.azconfig.io;Id={id};Secret={secret}"
  }
}

Connection String Format:

Endpoint=https://{store-name}.azconfig.io;Id={id};Secret={secret}

Connection String Components: - Endpoint: The Azure App Configuration store endpoint URL - Id: Client ID (for connection string authentication) - Secret: Client secret (for connection string authentication)

Managed Identity Authentication

For production, use managed identity instead of connection strings:

options.Connect(new Uri("https://{store-name}.azconfig.io"), 
    new DefaultAzureCredential());

Benefits: - No secrets in configuration - Automatic credential rotation - Better security posture - Supports Azure AD authentication

Key Vault References

Use Key Vault references for connection strings:

{
  "ConnectionStrings": {
    "AzureAppConfiguration": "@Microsoft.KeyVault(SecretUri=https://{vault}.vault.azure.net/secrets/{secret-name})"
  }
}

Benefits: - Centralized secret management - Automatic secret rotation - Audit logging - Access control

Key Selection

Key Pattern Matching

Select Keys by Pattern:

.Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null)

Pattern Components: - ConnectSoft.MicroserviceTemplate:*: Matches all keys starting with this prefix - LabelFilter.Null: Only keys without labels (Production)

Examples:

// Select all keys with prefix
.Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null)

// Select specific keys
.Select("ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName", LabelFilter.Null)

// Select multiple patterns
.Select("ConnectSoft.MicroserviceTemplate:Microservice:*", LabelFilter.Null)
.Select("ConnectSoft.MicroserviceTemplate:Validation:*", LabelFilter.Null)

Environment Labels

Multi-Environment Support:

options.Connect(connectionString)
    // Production keys (no label)
    .Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null)

    // Development overrides
    .Select("ConnectSoft.MicroserviceTemplate:*", "Development")

    // Staging overrides
    .Select("ConnectSoft.MicroserviceTemplate:*", "Staging");

Label Priority: 1. Environment-specific label (Development, Staging, etc.) 2. Null label (Production) 3. Base configuration (appsettings.json)

Example:

Production (Label: null):
  ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName = "ProductionService"

Development (Label: Development):
  ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName = "DevelopmentService"

Result in Development environment: "DevelopmentService" (overrides Production)

Dynamic Configuration Refresh

Sentinel Key Strategy

Purpose: Use a single sentinel key to trigger full configuration refresh.

Configuration:

.ConfigureRefresh(refresh =>
{
    refresh.Register(
        "ConnectSoft.MicroserviceTemplate:Settings:Sentinel", 
        refreshAll: true);
    refresh.SetRefreshInterval(TimeSpan.FromMinutes(30));
})

How It Works: 1. Middleware polls the sentinel key at configured interval 2. If sentinel key value changes, all configuration is refreshed 3. IOptionsMonitor<T> instances are updated 4. Change notifications are triggered

Benefits: - Efficient: Only one key needs to be checked - Atomic: All configuration refreshes together - Predictable: Clear trigger for refresh - Performance: Minimal overhead

Refresh Interval

Configure Polling Interval:

refresh.SetRefreshInterval(TimeSpan.FromMinutes(30));

Considerations: - Shorter intervals: More responsive but higher API calls - Longer intervals: Fewer API calls but slower updates - Default: 30 minutes is a good balance

Recommended Intervals: - Development: 1-5 minutes (faster feedback) - Staging: 5-15 minutes (balance) - Production: 15-30 minutes (stability)

Manual Refresh Keys

Register Specific Keys for Refresh:

.ConfigureRefresh(refresh =>
{
    // Sentinel key (triggers full refresh)
    refresh.Register("ConnectSoft.MicroserviceTemplate:Settings:Sentinel", refreshAll: true);

    // Specific keys (refresh only these)
    refresh.Register("ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName");
    refresh.Register("ConnectSoft.MicroserviceTemplate:Validation:EnableClassLevelFailFast");

    refresh.SetRefreshInterval(TimeSpan.FromMinutes(30));
})

When to Use: - Specific keys that change frequently - Keys that need immediate updates - Fine-grained refresh control

Dynamic Configuration Usage

IOptionsMonitor

Use IOptionsMonitor<T> for Dynamic Configuration:

public class ConfigurableService
{
    private readonly IOptionsMonitor<MicroserviceOptions> optionsMonitor;
    private readonly ILogger<ConfigurableService> logger;

    public ConfigurableService(
        IOptionsMonitor<MicroserviceOptions> optionsMonitor,
        ILogger<ConfigurableService> logger)
    {
        this.optionsMonitor = optionsMonitor;
        this.logger = logger;

        // Subscribe to configuration changes
        this.optionsMonitor.OnChange(options =>
        {
            this.logger.LogInformation(
                "Configuration updated: {MicroserviceName}", 
                options.MicroserviceName);
        });
    }

    public void Process()
    {
        // Always gets latest value (even after refresh)
        var currentConfig = this.optionsMonitor.CurrentValue;

        // Use configuration
        var serviceName = currentConfig.MicroserviceName;
    }
}

Benefits: - Always Current: Gets latest value even after refresh - Change Notifications: Subscribe to configuration changes - Singleton: One instance shared across application - Thread-Safe: Safe to use in concurrent scenarios

IOptionsSnapshot

Use IOptionsSnapshot<T> for Scoped Configuration:

public class ScopedService
{
    private readonly IOptionsSnapshot<MicroserviceOptions> optionsSnapshot;

    public ScopedService(IOptionsSnapshot<MicroserviceOptions> optionsSnapshot)
    {
        this.optionsSnapshot = optionsSnapshot;
    }

    public void Process()
    {
        // Gets configuration at request start (scoped)
        var config = this.optionsSnapshot.Value;
    }
}

Characteristics: - Scoped Lifetime: One instance per request - Snapshot: Captures configuration at request start - Reloadable: Gets updated values on refresh - Per-Request: Each request gets its own snapshot

IOptions

Use IOptions<T> for Immutable Configuration:

public class ImmutableService
{
    private readonly MicroserviceOptions options;

    public ImmutableService(IOptions<MicroserviceOptions> options)
    {
        this.options = options.Value; // Loaded once at startup
    }

    public void Process()
    {
        // Uses configuration loaded at startup (immutable)
        var serviceName = this.options.MicroserviceName;
    }
}

Characteristics: - Immutable: Loaded once at startup - Singleton: Same instance throughout application lifetime - Not Reloadable: Does not update on refresh - Performance: No overhead for configuration access

Feature Flags Integration

Enable Feature Flags

Configuration:

#if UseAzureAppConfigurationAsFeatureFlagsProvider
options.UseFeatureFlags(featureFlagsOptions =>
{
    featureFlagsOptions.Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null);
    featureFlagsOptions.SetRefreshInterval(TimeSpan.FromMinutes(30));
});
#endif

Features: - Dynamic Updates: Change flags without redeployment - Environment Labels: Different flags per environment - Centralized Management: Manage flags in Azure portal - Automatic Refresh: Flags refresh with configuration

See Feature Flags for detailed feature flag documentation.

Client Options

Retry Configuration

Configure Retry Policy:

.ConfigureClientOptions(options =>
{
    options.Retry.MaxRetries = 1;
})

Retry Options: - MaxRetries: Maximum number of retry attempts - Mode: Retry mode (Exponential, Fixed, NoRetry) - Delay: Delay between retries - MaxDelay: Maximum delay between retries

Recommended Settings: - Development: MaxRetries = 1 (fail fast for debugging) - Production: MaxRetries = 3 (resilience for transient failures)

Timeout Configuration

Configure Timeout:

.ConfigureClientOptions(options =>
{
    options.Retry.MaxRetries = 1;
    options.Timeout = TimeSpan.FromSeconds(30);
})

Key Naming Conventions

Use Hierarchical Keys:

ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName
ConnectSoft.MicroserviceTemplate:Validation:EnableClassLevelFailFast
ConnectSoft.MicroserviceTemplate:Orleans:Connection:ConnectionString

Pattern Structure: - {Organization}:{Service}:{Category}:{Property} - Use colons (:) as separators - Use PascalCase for segments

Benefits: - Organization: Clear hierarchy and grouping - Filtering: Easy to select related keys - Clarity: Self-documenting key structure - Consistency: Standardized naming across services

Key Examples

Microservice Configuration:

ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName
ConnectSoft.MicroserviceTemplate:Microservice:StartupWarmupSeconds

Validation Configuration:

ConnectSoft.MicroserviceTemplate:Validation:EnableClassLevelFailFast
ConnectSoft.MicroserviceTemplate:Validation:EnableRuleLevelFailFast

Orleans Configuration:

ConnectSoft.MicroserviceTemplate:Orleans:OrleansEndpoints:SiloPort
ConnectSoft.MicroserviceTemplate:Orleans:OrleansEndpoints:GatewayPort

Azure Portal Configuration

Creating Configuration Keys

Steps: 1. Navigate to Azure App Configuration store 2. Go to "Configuration explorer" 3. Click "Create" → "Key-value" 4. Enter key name (e.g., ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName) 5. Enter value 6. Optionally add label (e.g., "Development", "Staging") 7. Click "Apply"

Creating Sentinel Key

Sentinel Key: - Key: ConnectSoft.MicroserviceTemplate:Settings:Sentinel - Value: Timestamp (e.g., 2025-01-15T10:30:00Z) - Purpose: Trigger configuration refresh

Update Sentinel Key: 1. Navigate to sentinel key in Azure portal 2. Update value to current timestamp 3. Save changes 4. Configuration refreshes within refresh interval

Feature Flags in Portal

Create Feature Flag: 1. Navigate to "Feature manager" 2. Click "Create" 3. Enter feature flag name 4. Configure filters (percentage, time window, targeting) 5. Set enabled/disabled state 6. Optionally add label for environment-specific flags

Best Practices

Do's

  1. Use Hierarchical Key Names

    // ✅ GOOD
    ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName
    ConnectSoft.MicroserviceTemplate:Validation:EnableClassLevelFailFast
    
    // ❌ BAD
    MicroserviceName
    ValidationFailFast
    

  2. Use Sentinel Key for Refresh

    // ✅ GOOD - Efficient sentinel key
    refresh.Register("ConnectSoft.MicroserviceTemplate:Settings:Sentinel", refreshAll: true);
    
    // ❌ BAD - Polling all keys
    refresh.Register("ConnectSoft.MicroserviceTemplate:*", refreshAll: true);
    

  3. Use IOptionsMonitor for Dynamic Config

    // ✅ GOOD - Gets latest value
    public MyService(IOptionsMonitor<MyOptions> optionsMonitor)
    {
        var config = optionsMonitor.CurrentValue; // Always current
    }
    
    // ❌ BAD - Immutable, won't update
    public MyService(IOptions<MyOptions> options)
    {
        var config = options.Value; // Loaded once
    }
    

  4. Use Environment Labels

    // ✅ GOOD - Environment-specific overrides
    .Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null)  // Production
    .Select("ConnectSoft.MicroserviceTemplate:*", "Development")     // Development
    
    // ❌ BAD - No environment separation
    .Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null)
    

  5. Use Managed Identity in Production

    // ✅ GOOD - No secrets
    options.Connect(new Uri("https://store.azconfig.io"), new DefaultAzureCredential());
    
    // ❌ BAD - Connection string with secrets
    options.Connect(connectionStringWithSecret);
    

Don'ts

  1. Don't Store Secrets Directly

    // ❌ BAD - Secret in configuration
    "ApiKey": "sk-1234567890abcdef"
    
    // ✅ GOOD - Key Vault reference
    "ApiKey": "@Microsoft.KeyVault(SecretUri=https://vault.vault.azure.net/secrets/ApiKey)"
    

  2. Don't Poll Too Frequently

    // ❌ BAD - Too frequent, high API costs
    refresh.SetRefreshInterval(TimeSpan.FromSeconds(10));
    
    // ✅ GOOD - Balanced interval
    refresh.SetRefreshInterval(TimeSpan.FromMinutes(30));
    

  3. Don't Use IOptions for Dynamic Config

    // ❌ BAD - Won't update on refresh
    public MyService(IOptions<MyOptions> options)
    {
        this.options = options.Value; // Immutable
    }
    
    // ✅ GOOD - Updates on refresh
    public MyService(IOptionsMonitor<MyOptions> optionsMonitor)
    {
        this.optionsMonitor = optionsMonitor; // Dynamic
    }
    

  4. Don't Ignore Refresh Failures

    // ✅ GOOD - Handle refresh failures
    this.optionsMonitor.OnChange(options =>
    {
        try
        {
            this.logger.LogInformation("Configuration updated");
            // Update service state
        }
        catch (Exception ex)
        {
            this.logger.LogError(ex, "Failed to apply configuration update");
            // Fallback to previous configuration
        }
    });
    

Monitoring and Observability

Configuration Refresh Events

Log Configuration Changes:

this.optionsMonitor.OnChange(options =>
{
    this.logger.LogInformation(
        "Configuration refreshed at {Time}. MicroserviceName: {Name}", 
        DateTime.UtcNow, 
        options.MicroserviceName);
});

Metrics

Track Configuration Refresh:

private readonly Counter<int> configurationRefreshCounter;

public ConfigurableService(IOptionsMonitor<MyOptions> optionsMonitor)
{
    this.optionsMonitor.OnChange(options =>
    {
        this.configurationRefreshCounter.Add(1, 
            new KeyValuePair<string, object?>("EventType", "ConfigurationRefresh"));
    });
}

Health Checks

Monitor Azure App Configuration Health:

services.AddHealthChecks()
    .AddAzureAppConfiguration(
        options =>
        {
            options.ConnectionString = configuration.GetConnectionString("AzureAppConfiguration");
        },
        name: "azure-app-configuration",
        failureStatus: HealthStatus.Degraded);

Troubleshooting

Issue: Configuration Not Refreshing

Symptom: Changes in Azure App Configuration don't reflect in application.

Solutions: 1. Verify UseMicroserviceAzureAppConfiguration() middleware is registered 2. Check sentinel key is being updated 3. Verify refresh interval is appropriate 4. Check connection string is valid 5. Review application logs for refresh errors 6. Verify keys match selection pattern 7. Check label filters match key labels

Issue: Connection String Authentication Fails

Symptom: UnauthorizedAccessException or authentication errors.

Solutions: 1. Verify connection string format is correct 2. Check connection string is not expired 3. Verify access keys in Azure portal 4. Consider using managed identity instead 5. Check network connectivity to Azure App Configuration

Issue: Keys Not Loading

Symptom: Configuration keys from Azure App Configuration not available.

Solutions: 1. Verify key selection pattern matches keys 2. Check label filters (Null vs environment labels) 3. Verify connection string is correct 4. Check keys exist in Azure portal 5. Verify key names match exactly (case-sensitive)

Issue: Performance Issues

Symptom: Slow application startup or high latency.

Solutions: 1. Reduce number of keys selected 2. Increase refresh interval 3. Use specific key patterns instead of wildcards 4. Check network latency to Azure App Configuration 5. Consider caching configuration locally

Integration with Other Patterns

Azure App Configuration + Options Pattern

Seamless Integration:

// Configuration from Azure App Configuration
{
    "ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName": "MyService"
}

// Options class
public sealed class MicroserviceOptions
{
    public const string SectionName = "Microservice";
    [Required]
    required public string MicroserviceName { get; set; }
}

// Usage
public MyService(IOptionsMonitor<MicroserviceOptions> optionsMonitor)
{
    // Automatically bound from Azure App Configuration
    var name = optionsMonitor.CurrentValue.MicroserviceName;
}

Azure App Configuration + Feature Flags

Unified Management:

options.Connect(connectionString)
    .Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null)
    .ConfigureRefresh(...)
    .UseFeatureFlags(featureFlagsOptions =>
    {
        featureFlagsOptions.Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null);
    });

Benefits: - Single Source: Configuration and feature flags in one place - Consistent Labels: Same environment labels for both - Unified Refresh: Both refresh together - Centralized Management: Manage in Azure portal

Azure App Configuration + Key Vault

Secure Secret Management:

{
  "ConnectionStrings": {
    "AzureAppConfiguration": "@Microsoft.KeyVault(SecretUri=https://vault.vault.azure.net/secrets/AppConfigConnectionString)"
  }
}

Key Vault References in Configuration:

ConnectSoft.MicroserviceTemplate:Database:ConnectionString
Value: @Microsoft.KeyVault(SecretUri=https://vault.vault.azure.net/secrets/DbConnectionString)

Benefits: - Centralized Secrets: All secrets in Key Vault - Automatic Rotation: Key Vault handles secret rotation - Access Control: Role-based access to secrets - Audit Logging: Track secret access

Security Considerations

Connection String Security

Development: - Use connection strings in User Secrets or environment variables - Never commit connection strings to source control

Production: - Use managed identity authentication - Use Key Vault references for connection strings - Rotate access keys regularly - Use read-only access keys when possible

Access Control

Role-Based Access Control (RBAC): - App Configuration Data Reader: Read-only access - App Configuration Data Owner: Full access - App Configuration Data Contributor: Read and write access

Recommended: - Application: App Configuration Data Reader - Administrators: App Configuration Data Owner - CI/CD: App Configuration Data Contributor

Key Vault Integration

Reference Secrets:

Key: ConnectSoft.MicroserviceTemplate:Database:ConnectionString
Value: @Microsoft.KeyVault(SecretUri=https://vault.vault.azure.net/secrets/DbConnectionString)

Benefits: - Secrets never stored in App Configuration - Automatic secret rotation - Centralized secret management - Audit logging

Cost Optimization

Key Selection

Optimize Key Selection:

// ✅ GOOD - Specific keys
.Select("ConnectSoft.MicroserviceTemplate:Microservice:MicroserviceName", LabelFilter.Null)
.Select("ConnectSoft.MicroserviceTemplate:Validation:EnableClassLevelFailFast", LabelFilter.Null)

// ❌ BAD - Too broad, loads unnecessary keys
.Select("ConnectSoft.MicroserviceTemplate:*", LabelFilter.Null)

Refresh Interval

Balance Responsiveness and Cost:

// ✅ GOOD - Balanced interval
refresh.SetRefreshInterval(TimeSpan.FromMinutes(30));

// ❌ BAD - Too frequent, high API costs
refresh.SetRefreshInterval(TimeSpan.FromSeconds(10));

Caching

Leverage Built-in Caching: - Azure App Configuration client caches configuration - Refresh only checks for changes - Minimal API calls when configuration is stable

Summary

Azure App Configuration in the ConnectSoft Microservice Template provides:

  • Centralized Management: Single source of truth for configuration
  • Dynamic Updates: Change configuration without redeployment
  • Environment Support: Labels for multi-environment configurations
  • Feature Flags: Built-in feature flag management
  • Security: Key Vault integration and managed identity support
  • Performance: Efficient polling and caching
  • Scalability: Supports thousands of configuration keys
  • Governance: RBAC, audit logs, and versioning

By following these patterns, teams can:

  • Centralize Configuration: Manage configuration across multiple services
  • Update Dynamically: Change configuration without redeployment
  • Support Multi-Environment: Use labels for environment-specific configs
  • Secure Secrets: Integrate with Key Vault for secret management
  • Monitor Changes: Track configuration updates and refresh events
  • Optimize Costs: Balance refresh frequency and API usage

Azure App Configuration enables teams to manage configuration at scale, update settings dynamically, and maintain consistency across microservices while providing security, observability, and performance optimizations.