Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Azure App Configuration is a managed service that helps developers centralize their application configurations simply and securely. The Go configuration provider library enables loading configuration from an Azure App Configuration store in a managed way. This client library adds additional functionality on top of the Azure SDK for Go.
Load configuration
The Azure App Configuration Go provider allows you to load configuration values from your Azure App Configuration store into your Go applications. You can connect using either Microsoft Entra ID authentication or a connection string.
To use the Go configuration provider, install the package:
go get github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration
You call the Load function from the azureappconfiguration package to load configuration from Azure App Configuration. The Load function accepts authentication options and configuration options to customize the loading behavior.
You can use the DefaultAzureCredential, or any other token credential implementation, to authenticate to your App Configuration store. Follow the instructions to assign your credential the App Configuration Data Reader role.
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
func main() {
ctx := context.Background()
// Get the endpoint from environment variable
endpoint := os.Getenv("AZURE_APPCONFIG_ENDPOINT")
// Create a credential using DefaultAzureCredential
credential, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
log.Fatalf("Failed to create credential: %v", err)
}
// Set up authentication options
authOptions := azureappconfiguration.AuthenticationOptions{
Endpoint: endpoint,
Credential: credential,
}
// Load configuration from Azure App Configuration
appConfig, err := azureappconfiguration.Load(ctx, authOptions, nil)
if err != nil {
log.Fatalf("Failed to load configuration: %v", err)
}
}
Load specific key-values using selectors
By default, the configuration provider loads all key-values with no label from App Configuration. You can selectively load key-values by configuring the Selectors field in the Options struct.
options := &azureappconfiguration.Options{
Selectors: []azureappconfiguration.Selector{
{
// Load configuration values with prefix "App:" and no label
KeyFilter: "App:*",
LabelFilter: "",
},
{
// Load configuration values with prefix "App:" and "Prod" label
KeyFilter: "App:*",
LabelFilter: "Prod",
},
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
The Selector struct supports the following fields:
- KeyFilter: Determines which configuration keys to include. Use exact matches, prefix matching with
*, or comma-separated multiple keys. - LabelFilter: Selects key-values with a specific label. If empty, loads key-values with no label.
Note
When multiple selectors include overlapping keys, later selectors take precedence over earlier ones.
Tag filters
The TagFilters parameter selects key-values with specific tags. A key-value is only loaded if it has all of the tags and corresponding values specified in the filters.
options := &azureappconfiguration.Options{
Selectors: []azureappconfiguration.Selector{
{
// Load configuration values with prefix "App:" and specific tags
KeyFilter: "App:*",
TagFilters: []string{"env=prod"},
},
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
Note
The characters asterisk (*), comma (,), and backslash (\) are reserved and must be escaped with a backslash when used in a tag filter.
Trim prefix from keys
When loading configuration values with specific prefixes, you can use the TrimKeyPrefixes option to remove those prefixes from the keys in your configuration. This creates cleaner configuration keys in your application while maintaining organization in your App Configuration store.
options := &azureappconfiguration.Options{
// Load configuration values with prefix "TestApp:" and trim the prefix
Selectors: []azureappconfiguration.Selector{
{
KeyFilter: "TestApp:*",
},
},
TrimKeyPrefixes: []string{"TestApp:"},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
For example, if your App Configuration store contains a key named TestApp:Settings:Message, it will be accessible in your application as Settings:Message after trimming the TestApp: prefix.
JSON content type handling
You can create JSON key-values in App Configuration. When a key-value with the content type "application/json" is read, the configuration provider will parse it into nested structures. For more information, go to Use content type to store JSON key-values in App Configuration.
Consume configuration
The AzureAppConfiguration type returned by the Load function provides several methods to access your configuration data:
Unmarshal to structs
The Unmarshal method provides a type-safe way to load configuration values into Go structs. This approach prevents runtime errors from mistyped configuration keys and makes your code more maintainable. The method accepts an optional ConstructionOptions parameter to customize how configuration keys are mapped to struct fields.
type Config struct {
Message string
App struct {
Name string
Debug bool
Settings struct {
Timeout int
RetryCount int
}
}
}
func main() {
// ... load configuration ...
// Create a configuration struct and unmarshal into it
var config Config
if err := appConfig.Unmarshal(&config, nil); err != nil {
log.Fatalf("Failed to unmarshal configuration: %v", err)
}
// Access configuration values
fmt.Printf("Message: %s\n", config.Message)
fmt.Printf("App Name: %s\n", config.App.Name)
fmt.Printf("Debug Mode: %t\n", config.App.Debug)
fmt.Printf("Timeout: %d seconds\n", config.App.Settings.Timeout)
}
Custom key separators
You can customize how configuration keys are mapped to struct fields using ConstructionOptions. This is useful when your configuration keys use different separators than the default dot (.):
// Configuration keys using colon separator: "App:Name", "App:Settings:Timeout"
constructionOptions := &azureappconfiguration.ConstructionOptions{
Separator: ":",
}
var config Config
if err := appConfig.Unmarshal(&config, constructionOptions); err != nil {
log.Fatalf("Failed to unmarshal configuration: %v", err)
}
The ConstructionOptions struct supports the following separators: ., ,, ;, -, _, __, /, :. If not specified, the default separator . is used.
Get raw JSON bytes
The GetBytes method retrieves your configuration as raw JSON data, offering flexibility for integration with JSON processing libraries or configuration frameworks like viper. This method also accepts an optional ConstructionOptions parameter to control key hierarchy mapping.
// Get configuration as JSON bytes with default separator
jsonBytes, err := appConfig.GetBytes(nil)
if err != nil {
log.Fatalf("Failed to get configuration as bytes: %v", err)
}
fmt.Println("Raw JSON Configuration:")
fmt.Println(string(jsonBytes))
// Get configuration with custom separator
constructionOptions := &azureappconfiguration.ConstructionOptions{
Separator: ":",
}
jsonBytes, err = appConfig.GetBytes(constructionOptions)
if err != nil {
log.Fatalf("Failed to get configuration as bytes: %v", err)
}
// Example: Use with viper
v := viper.New()
v.SetConfigType("json")
if err := v.ReadConfig(bytes.NewBuffer(jsonBytes)); err != nil {
log.Fatalf("Failed to read config into viper: %v", err)
}
Configuration refresh
Configuring refresh enables the application to pull the latest values from the App Configuration store without having to restart. You can configure refresh options using the RefreshOptions field in the Options struct. The loaded configuration will be updated when any change of selected key-values is detected on the server. By default, a refresh interval of 30 seconds is used, but you can override it with the Interval property.
options := &azureappconfiguration.Options{
// Load all keys that start with `TestApp:` and have no label
Selectors: []azureappconfiguration.Selector{
{
KeyFilter: "TestApp:*",
LabelFilter: "",
},
},
// Trigger full configuration refresh when any selected key changes
RefreshOptions: azureappconfiguration.KeyValueRefreshOptions{
Enabled: true,
// Check for changes no more often than every 60 seconds
Interval: 60 * time.Second,
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
Setting up RefreshOptions alone won't automatically refresh the configuration. You need to call the Refresh method on the AzureAppConfiguration instance to trigger a refresh.
// Trigger a refresh
if err := appConfig.Refresh(ctx); err != nil {
log.Printf("Failed to refresh configuration: %v", err)
}
This design prevents unnecessary requests to App Configuration when your application is idle. You should include the Refresh call where your application activity occurs. This is known as activity-driven configuration refresh. For example, you can call Refresh when processing an incoming request or inside an iteration where you perform a complex task.
Note
Even if the refresh call fails for any reason, your application continues to use the cached configuration. Another attempt will be made when the configured refresh interval has passed and the refresh call is triggered by your application activity. Calling Refresh is a no-op before the configured refresh interval elapses, so its performance impact is minimal even if it's called frequently.
Refresh on sentinel key
A sentinel key is a key that you update after you complete the change of all other keys. The configuration provider monitors the sentinel key instead of all selected key-values. When a change is detected, your app refreshes all configuration values.
This approach is useful when updating multiple key-values. By updating the sentinel key only after all other configuration changes are completed, you ensure your application reloads configuration just once, maintaining consistency.
options := &azureappconfiguration.Options{
// Load all keys that start with `TestApp:` and have no label
Selectors: []azureappconfiguration.Selector{
{
KeyFilter: "TestApp:*",
LabelFilter: "",
},
},
// Trigger full configuration refresh only if the `SentinelKey` changes
RefreshOptions: azureappconfiguration.KeyValueRefreshOptions{
Enabled: true,
WatchedSettings: []azureappconfiguration.WatchedSetting{
{
Key: "SentinelKey",
Label: "",
},
},
},
}
Custom refresh callback
The OnRefreshSuccess method registers a callback function that will be executed whenever the configuration is successfully refreshed and actual changes were detected.
var config Config
if err := appConfig.Unmarshal(&config, nil); err != nil {
log.Fatalf("Failed to unmarshal configuration: %v", err)
}
// Register refresh callback
appConfig.OnRefreshSuccess(func() {
// Re-unmarshal the configuration
err := appConfig.Unmarshal(&config, nil)
if err != nil {
log.Printf("Failed to unmarshal updated configuration: %s", err)
return
}
})
Feature flags
Feature flags in Azure App Configuration provide a modern way to control feature availability in your applications. Unlike regular configuration values, feature flags must be explicitly loaded using the FeatureFlagOptions field in the Options struct.
options := &azureappconfiguration.Options{
FeatureFlagOptions: azureappconfiguration.FeatureFlagOptions{
Enabled: true,
// Load feature flags that start with `TestApp:` and have `dev` label
Selectors: []azureappconfiguration.Selector{
{
KeyFilter: "TestApp:*",
LabelFilter: "dev",
},
},
RefreshOptions: azureappconfiguration.RefreshOptions{
Enabled: true,
Interval: 60 * time.Second,
},
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
Tip
When no selector is specified in FeatureFlagOptions, it loads all feature flags with no label in your App Configuration store. The default refresh interval of feature flags is 30 seconds.
Important
To effectively consume and manage feature flags loaded from Azure App Configuration, install and use the featuremanagement package. This library provides a structured way to control feature behavior in your application.
Feature management
The Feature Management Go library provides a structured way to develop and expose application functionality based on feature flags. The feature management library is designed to work in conjunction with the configuration provider library.
To use feature flags with the feature management library, install the required packages:
go get github.com/microsoft/Featuremanagement-Go/featuremanagement
go get github.com/microsoft/Featuremanagement-Go/featuremanagement/providers/azappconfig
The following example demonstrates how to integrate the feature management library with the configuration provider to dynamically control feature availability:
import (
"github.com/microsoft/Featuremanagement-Go/featuremanagement"
"github.com/microsoft/Featuremanagement-Go/featuremanagement/providers/azappconfig"
)
func main() {
// Set up authentication options
authOptions := azureappconfiguration.AuthenticationOptions{
Endpoint: endpoint,
Credential: credential,
}
// Load configuration with feature flags enabled
options := &azureappconfiguration.Options{
FeatureFlagOptions: azureappconfiguration.FeatureFlagOptions{
Enabled: true,
RefreshOptions: azureappconfiguration.RefreshOptions{
Enabled: true,
},
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
if err != nil {
log.Fatalf("Failed to load configuration: %v", err)
}
// Create feature flag provider using the Azure App Configuration
featureFlagProvider, err := azappconfig.NewFeatureFlagProvider(appConfig)
if err != nil {
log.Fatalf("Error creating feature flag provider: %v", err)
}
// Create feature manager
featureManager, err := featuremanagement.NewFeatureManager(featureFlagProvider, nil)
if err != nil {
log.Fatalf("Error creating feature manager: %v", err)
}
// Use the feature manager to check feature flags
isEnabled, err := featureManager.IsEnabled("Beta")
if err != nil {
log.Printf("Error checking feature flag: %v", err)
return
}
if isEnabled {
fmt.Println("Beta feature is enabled!")
// Execute beta functionality
} else {
fmt.Println("Beta feature is disabled")
// Execute standard functionality
}
}
For more information about how to use the Go feature management library, go to the feature flag quickstart.
Key Vault reference
Azure App Configuration supports referencing secrets stored in Azure Key Vault. In App Configuration, you can create keys that map to secrets stored in Key Vault, but can be accessed like any other configuration once loaded.
The configuration provider library retrieves Key Vault references, just as it does for any other keys stored in App Configuration. You need to configure Key Vault access using the KeyVaultOptions field in the Options struct.
Connect to Key Vault
You can configure Key Vault access by providing credentials that can authenticate to your Key Vault instances.
import (
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
// Create a credential for Key Vault access
credential, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
log.Fatalf("Failed to create credential: %v", err)
}
options := &azureappconfiguration.Options{
KeyVaultOptions: azureappconfiguration.KeyVaultOptions{
Credential: credential,
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
Custom secret resolver
You can also provide a custom secret resolver function to handle Key Vault references when the default credential-based approach is not suitable:
options := &azureappconfiguration.Options{
KeyVaultOptions: azureappconfiguration.KeyVaultOptions{
SecretResolver: func(ctx context.Context, keyVaultReference url.URL) (string, error) {
// Custom logic to resolve secrets
// This could integrate with your existing secret management system
// or provide fallback values for development environments
if isDevelopment {
return os.Getenv("FALLBACK_SECRET_VALUE"), nil
}
// Implement your custom secret retrieval logic here
return retrieveSecret(keyVaultReference)
},
},
}
Important
If your application loads key-values containing Key Vault references without proper Key Vault configuration, an error will be returned during the load operation. Ensure you've properly configured Key Vault access or a secret resolver.
Key Vault secret refresh
Azure App Configuration enables you to configure secret refresh intervals independently of your configuration refresh cycle. This is crucial for security because while the Key Vault reference URI in App Configuration remains unchanged, the underlying secret in Key Vault might be rotated as part of your security practices.
To ensure your application always uses the most current secret values, configure the RefreshOptions field in the KeyVaultOptions struct.
import (
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
// Create a credential for Key Vault access
credential, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
log.Fatalf("Failed to create credential: %v", err)
}
options := &azureappconfiguration.Options{
KeyVaultOptions: azureappconfiguration.KeyVaultOptions{
Credential: credential,
RefreshOptions: azureappconfiguration.RefreshOptions{
Enabled: true,
Interval: 5 * time.Minute,
},
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
Snapshot
Snapshot is a named, immutable subset of an App Configuration store's key-values. The key-values that make up a snapshot are chosen during creation time through the usage of key and label filters. Once a snapshot is created, the key-values within are guaranteed to remain unchanged.
You can configure SnapshotName filed in the Selector struct to load key-values from a snapshot:
options := &azureappconfiguration.Options{
Selectors: []azureappconfiguration.Selector{
{KeyFilter: "app*", LabelFilter: "prod"},
{SnapshotName: "my-snapshot"},
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
Geo-replication
For information about using geo-replication, go to Enable geo-replication.
Startup retry
Configuration loading is a critical path operation during application startup. To ensure reliability, the Azure App Configuration provider implements a robust retry mechanism during the initial configuration load. This helps protect your application from transient network issues that might otherwise prevent successful startup.
You can customize this behavior via the Options.StartupOptions:
options := &azureappconfiguration.Options{
StartupOptions: azureappconfiguration.StartupOptions{
Timeout: 5 * time.Minute,
},
}
appConfig, err := azureappconfiguration.Load(ctx, authOptions, options)
Next steps
To learn how to use the Go configuration provider, continue to the following tutorial.