Azure App Configuration SDK for TypeScript
Centralized configuration management with feature flags and dynamic refresh.
Installation
Low-level CRUD SDK
npm install @azure/app-configuration @azure/identity
High-level provider (recommended for apps)
npm install @azure/app-configuration-provider @azure/identity
Feature flag management
npm install @microsoft/feature-management
Environment Variables
AZURE_APPCONFIG_ENDPOINT=https://<your-resource>.azconfig.io
OR
AZURE_APPCONFIG_CONNECTION_STRING=Endpoint=https://...;Id=...;Secret=...
Authentication
import { AppConfigurationClient } from "@azure/app-configuration"; import { DefaultAzureCredential } from "@azure/identity";
// DefaultAzureCredential (recommended) const client = new AppConfigurationClient( process.env.AZURE_APPCONFIG_ENDPOINT!, new DefaultAzureCredential() );
// Connection string const client2 = new AppConfigurationClient( process.env.AZURE_APPCONFIG_CONNECTION_STRING! );
CRUD Operations
Create/Update Settings
// Add new (fails if exists) await client.addConfigurationSetting({ key: "app:settings:message", value: "Hello World", label: "production", contentType: "text/plain", tags: { environment: "prod" }, });
// Set (create or update) await client.setConfigurationSetting({ key: "app:settings:message", value: "Updated value", label: "production", });
// Update with optimistic concurrency const existing = await client.getConfigurationSetting({ key: "myKey" }); existing.value = "new value"; await client.setConfigurationSetting(existing, { onlyIfUnchanged: true });
Read Settings
// Get single setting const setting = await client.getConfigurationSetting({ key: "app:settings:message", label: "production", // optional }); console.log(setting.value);
// List with filters const settings = client.listConfigurationSettings({ keyFilter: "app:*", labelFilter: "production", });
for await (const setting of settings) {
console.log(${setting.key}: ${setting.value});
}
Delete Settings
await client.deleteConfigurationSetting({ key: "app:settings:message", label: "production", });
Lock/Unlock (Read-Only)
// Lock await client.setReadOnly({ key: "myKey", label: "prod" }, true);
// Unlock await client.setReadOnly({ key: "myKey", label: "prod" }, false);
App Configuration Provider
Load Configuration
import { load } from "@azure/app-configuration-provider"; import { DefaultAzureCredential } from "@azure/identity";
const appConfig = await load( process.env.AZURE_APPCONFIG_ENDPOINT!, new DefaultAzureCredential(), { selectors: [ { keyFilter: "app:*", labelFilter: "production" }, ], trimKeyPrefixes: ["app:"], } );
// Map-style access const value = appConfig.get("settings:message");
// Object-style access const config = appConfig.constructConfigurationObject({ separator: ":" }); console.log(config.settings.message);
Dynamic Refresh
const appConfig = await load(endpoint, credential, { selectors: [{ keyFilter: "app:*" }], refreshOptions: { enabled: true, refreshIntervalInMs: 30_000, // 30 seconds }, });
// Trigger refresh (non-blocking) appConfig.refresh();
// Listen for refresh events const disposer = appConfig.onRefresh(() => { console.log("Configuration refreshed!"); });
// Express middleware pattern app.use((req, res, next) => { appConfig.refresh(); next(); });
Key Vault References
const appConfig = await load(endpoint, credential, { selectors: [{ keyFilter: "app:*" }], keyVaultOptions: { credential: new DefaultAzureCredential(), secretRefreshIntervalInMs: 7200_000, // 2 hours }, });
// Secrets are automatically resolved const dbPassword = appConfig.get("database:password");
Feature Flags
Create Feature Flag (Low-Level)
import { featureFlagPrefix, featureFlagContentType, FeatureFlagValue, ConfigurationSetting, } from "@azure/app-configuration";
const flag: ConfigurationSetting<FeatureFlagValue> = {
key: ${featureFlagPrefix}Beta,
contentType: featureFlagContentType,
value: {
id: "Beta",
enabled: true,
description: "Beta feature",
conditions: {
clientFilters: [
{
name: "Microsoft.Targeting",
parameters: {
Audience: {
Users: ["user@example.com"],
Groups: [{ Name: "beta-testers", RolloutPercentage: 50 }],
DefaultRolloutPercentage: 0,
},
},
},
],
},
},
};
await client.addConfigurationSetting(flag);
Load and Evaluate Feature Flags
import { load } from "@azure/app-configuration-provider"; import { ConfigurationMapFeatureFlagProvider, FeatureManager, } from "@microsoft/feature-management";
const appConfig = await load(endpoint, credential, { featureFlagOptions: { enabled: true, selectors: [{ keyFilter: "*" }], refresh: { enabled: true, refreshIntervalInMs: 30_000, }, }, });
const featureProvider = new ConfigurationMapFeatureFlagProvider(appConfig); const featureManager = new FeatureManager(featureProvider);
// Simple check const isEnabled = await featureManager.isEnabled("Beta");
// With targeting context const isEnabledForUser = await featureManager.isEnabled("Beta", { userId: "user@example.com", groups: ["beta-testers"], });
Snapshots
// Create snapshot const snapshot = await client.beginCreateSnapshotAndWait({ name: "release-v1.0", retentionPeriod: 2592000, // 30 days filters: [{ keyFilter: "app:*", labelFilter: "production" }], });
// Get snapshot const snap = await client.getSnapshot("release-v1.0");
// List settings in snapshot
const settings = client.listConfigurationSettingsForSnapshot("release-v1.0");
for await (const setting of settings) {
console.log(${setting.key}: ${setting.value});
}
// Archive/recover await client.archiveSnapshot("release-v1.0"); await client.recoverSnapshot("release-v1.0");
// Load from snapshot (provider) const config = await load(endpoint, credential, { selectors: [{ snapshotName: "release-v1.0" }], });
Labels
// Create settings with labels await client.setConfigurationSetting({ key: "database:host", value: "dev-db.example.com", label: "development", });
await client.setConfigurationSetting({ key: "database:host", value: "prod-db.example.com", label: "production", });
// Filter by label const prodSettings = client.listConfigurationSettings({ keyFilter: "*", labelFilter: "production", });
// No label (null label) const noLabelSettings = client.listConfigurationSettings({ labelFilter: "\0", });
// List available labels for await (const label of client.listLabels()) { console.log(label.name); }
Key Types
import { AppConfigurationClient, ConfigurationSetting, FeatureFlagValue, SecretReferenceValue, featureFlagPrefix, featureFlagContentType, secretReferenceContentType, ListConfigurationSettingsOptions, } from "@azure/app-configuration";
import { load } from "@azure/app-configuration-provider";
import { FeatureManager, ConfigurationMapFeatureFlagProvider, } from "@microsoft/feature-management";
Best Practices
-
Use provider for apps - @azure/app-configuration-provider for runtime config
-
Use low-level for management - @azure/app-configuration for CRUD operations
-
Enable refresh - For dynamic configuration updates
-
Use labels - Separate configurations by environment
-
Use snapshots - For immutable release configurations
-
Sentinel pattern - Use a sentinel key to trigger full refresh
-
RBAC roles - App Configuration Data Reader for read-only access