Azure App Configuration
Azure App Configuration is a managed store for the settings your application reads at runtime — connection strings, endpoints, timeouts, tuning knobs, and feature flags — held outside the application package so that changing one does not mean redeploying the other. It is a key-value store with two ideas bolted on that make it more than a database: labels, which let one key hold a different value per environment or per release, and feature flags as a first-class typed object with its own management UI and client library.
Names. No rename to catch here — it has been Azure App Configuration since general availability
in 2019. Watch out for the near-collisions instead: App Service application settings (the
per-app environment variables on a Web App), Azure Automation variables, and Kubernetes
ConfigMaps all solve a slice of the same problem, and Microsoft's own documentation sometimes
writes "app configuration" in lowercase meaning "the configuration of your app". The service is
Microsoft.AppConfiguration/configurationStores; if a document is talking about anything else, it
isn't this.
What it is and where it fits
Configuration has a natural lifecycle mismatch with code. Code changes when a developer merges a
pull request. Configuration changes when someone needs a timeout raised at 2 a.m., when a feature
should be visible to 5% of users, or when a downstream endpoint moves. If configuration lives in the
deployment artifact — appsettings.Production.json, a Helm values file, a pipeline variable group —
then every configuration change is a deployment, and every deployment carries the full risk and
latency of a deployment. That's the pain App Configuration exists to remove.
Think of it as a shared settings file that lives at a URL, with version history and access
control. Your app fetches it at startup, caches it in memory, and re-checks periodically. If a
value changed, the app picks it up without restarting. Nothing about that is technically hard — the
value is in the surrounding machinery: labels so dev, staging, and prod share one store without
sharing values; snapshots so a release can pin an immutable set of values; Key Vault references so
secrets stay in Key Vault while appearing in the same lookup namespace; revision history so "who
changed the timeout" has an answer; and feature-flag semantics so a percentage rollout is a filter
you configure rather than an if you deploy.
Azure's catalogue overlaps itself badly here, and picking the wrong door is the most common mistake:
- Key Vault — for secrets, and only secrets. Key Vault is hardened, audited, per-secret RBAC-scoped, backed by an HSM option, and comparatively slow and expensive per read. App Configuration is for non-secret settings and is cheaper and faster per read. The intended design is both: put the secret in Key Vault, put a Key Vault reference in App Configuration, and let the client resolve it. If you find yourself putting a password directly into App Configuration, you have chosen wrong.
- App Service / Functions application settings — the built-in per-app key-value store. Perfectly fine for one app with a handful of settings. It breaks down at the second app (nothing is shared), at the second environment (nothing is labelled), and at the first audit question (no history). App Configuration is what you graduate to; the two coexist happily, because app settings are the natural place to hold the one value that points at your App Configuration store.
- Azure Managed Redis / Azure Cache for Redis — people sometimes use a cache as a config store because it's already there. It has no history, no RBAC granularity, no schema, and no UI. Don't.
- Kubernetes ConfigMaps and Secrets — the Kubernetes-native answer, and not a competitor: the App Configuration Kubernetes Provider syncs from a store into ConfigMaps and Secrets, so workloads keep reading the Kubernetes objects they already read while the source of truth is central.
- Azure App Configuration vs. "feature flags as a product" (LaunchDarkly, Split, Unleash, Flagsmith) — App Configuration's feature management is real and improving (targeting filters, percentage rollout, variants, telemetry) but it is a thinner product than a dedicated experimentation platform. If your organisation runs experiments as a discipline with statistical significance testing and a metrics pipeline, evaluate the specialists honestly.
The honest summary: App Configuration is a small, cheap, unglamorous service that removes a whole class of deployment from your life — and it introduces exactly one new failure mode you must design for, which is what your application does when the store is unreachable at startup.
Key facts at a glance
| Category | Developer tools / application platform — configuration management |
| Resource provider | Microsoft.AppConfiguration/configurationStores, with child resources keyValues, replicas, snapshots, privateEndpointConnections |
| Scope | Regional, resource-group-scoped. The store lives in one region; geo-replication adds replicas in other regions, each with its own endpoint, under the same resource. See the scope hierarchy |
| Data-plane endpoint | https://<store-name>.azconfig.io — a separate endpoint from ARM, with separate RBAC. The store name is globally unique because it becomes a DNS label |
| SKU / tier axis | Free, Developer, Standard, Premium. This axis is the whole design decision: it gates storage size, request quota, private endpoints, geo-replication, customer-managed keys, soft delete, and the SLA. ⚠️ Tier names and inclusions have changed — verify against current Azure docs before committing to one |
| Unit of billing | A daily charge per store (per replica, on tiers that support replication) plus overage per block of requests beyond the tier's included allowance. Free tier has no daily charge but a hard daily request cap. Nothing is charged per key ⚠️ verify current pricing |
| SLA posture | No SLA on Free. A paid-tier availability SLA applies to the store; adding geo-replicas raises the composite availability of your system but the per-store SLA is what Microsoft commits to ⚠️ verify current SLA figures |
| Auth model | Microsoft Entra ID tokens (managed identity — the correct answer) or HMAC-signed access keys / connection strings. Local (key-based) auth can and generally should be disabled |
| Usual companions | Key Vault (secrets), Managed Identity, App Service / Functions / Container Apps / AKS (consumers), Event Grid (change notification), Azure Monitor (diagnostics), Private Link |
| Primary alternative | Application settings + a pipeline variable group (simpler, less capable), Kubernetes ConfigMaps (cluster-local), or a third-party feature-flag platform (richer experimentation) |
| AWS analogue | SSM Parameter Store for the key-value half and AWS AppConfig for the feature-flag half, rolled into one resource. The analogy breaks in two places: Azure has no service-side deployment strategy (AWS AppConfig can roll a config out gradually and auto-roll-back on a CloudWatch alarm — App Configuration cannot; gradual rollout happens client-side via filters), and Azure's label dimension has no Parameter Store equivalent (people fake it with path prefixes) |
When to use it
- More than one application, or more than one environment, sharing settings. The moment two things need the same endpoint URL, a central store beats copy-paste.
- You want to change a setting without a deployment. Timeouts, batch sizes, retry counts, circuit-breaker thresholds, downstream URLs — the operational dials.
- Feature flags with any sophistication. Percentage rollout, per-user or per-group targeting,
time windows, and kill switches, without an
if (Environment.GetEnvironmentVariable(...))in the codebase. - You need an audit trail on configuration. Revision history answers "what changed and when", and the diagnostic logs answer "who".
- Immutable, versioned config per release. Snapshots let a deployment pin a composed set of key-values that cannot subsequently drift, which is the closest thing to a config artifact.
- A fleet reading the same config — many instances, autoscaling, short-lived containers. One authoritative source beats a values file per chart.
When not to use it
- As a secret store. It encrypts at rest and supports private networking, but it has none of Key Vault's per-secret access model, HSM backing, expiry, rotation hooks, or certificate lifecycle. Use a Key Vault reference.
- As a database, cache, or feature store. Key-values are size-capped (single-digit kilobytes
each ⚠️ verify the current limit), request-quota-metered, and designed to be read at startup and
cached — not queried per user request. A per-request lookup will get you a
429. - For anything on the hot path with no local cache. The client libraries cache and poll for a reason. If you write your own HTTP calls and skip the cache, you have built a hard runtime dependency on a remote service into every request.
- For high-churn data. Values that change every few seconds don't belong here; that's a message or a cache, not configuration.
- When one app has five settings and always will. App Service application settings are free, already deployed, and adequate. Don't add a dependency to solve a problem you don't have.
- When you need service-side progressive rollout with automatic rollback. That's not what this is; the rollout logic lives in your app's feature-flag filters, and the rollback is you flipping a flag or re-pointing a snapshot.
Sub-topics
| Sub-topic | What it covers |
|---|---|
| What & Why | The deployment-coupling problem it kills, the neighbours it's confused with, the AWS analogy and where it breaks, and the honest anti-patterns |
| Core Concepts | Key-values, labels, content types, feature flags, Key Vault references, snapshots, revisions, replicas, and the four-tier SKU axis |
| Architecture | The read path end to end, control plane vs. data plane and their separate RBAC, geo-replication consistency, caching and the sentinel-key refresh model, throttling and failure modes |
| Getting Started | The same throwaway store three ways — Portal, az appconfig, and a minimal Terraform snippet — plus reading it from an app, and teardown |
| Deployment | A parameterised Terraform module, the features {} block that governs soft delete, remote state, the honest Ansible story, the Bicep equivalent with what-if, OIDC-based CI/CD, environment strategy, rollback, and drift |
| Integrations | Key Vault references, managed identity, App Service and Functions, Container Apps, the AKS Kubernetes provider, Event Grid change events, Private Link, and Azure Monitor |
| Production | Security and disabling local auth, cost and the request-overage trap, quota scopes, diagnostic settings and the KQL you'll actually run, and reliability via replicas and snapshots |
| Interview Questions | Three tiers with answer keys, from "what problem does it solve" to "Terraform can create the store but not the keys — why, and what's your fix" |
| Glossary & Cheatsheet | Every term in one line, the az appconfig commands worth memorising, the resource ID shape, and the limits with their scopes |
Three ideas worth carrying into every other page
The label is the whole design. A key without a label and the same key with label prod are two
different key-values, and clients select by label at read time. This is how one store serves every
environment — and it is also the sharpest edge in the service, because a client that forgets to
filter by label silently reads the no-label value, which is usually somebody's development default.
Decide your label convention before you create your first key, and treat "no label" as either
"shared across all environments" or "forbidden" — never as "the default environment".
Control plane and data plane are separate, and the seam leaks. ARM creates and configures the
store; the azconfig.io endpoint holds the key-values; each has its own RBAC. Being App
Configuration Contributor does not let you read a key-value — but it does let you read the
store's access keys, and those grant full data access. So the control-plane role is a
data-plane escalation path unless you disable local authentication. That single sentence is both the
most common interview question on this service and the most common real misconfiguration.
Your application must survive the store being unavailable. Configuration is read at startup, so
an outage or a throttled request at exactly the wrong moment is a failed start, not a degraded
request. Design for it explicitly: geo-replication with client-side failover, a startup timeout,
Optional: true on the configuration source, a baked-in fallback file for the values that must
exist, and a decision — written down — about whether the app should boot with stale config or refuse
to boot at all.
Reading paths
New to it — What & Why → Core Concepts → Getting Started. Create a Free-tier store, put three keys in it with two labels, read them from a console app, delete the resource group.
Coming from Parameter Store or AWS AppConfig — skim What & Why for the analogy break, then read the label and snapshot sections of Core Concepts and the refresh model in Architecture. Those three are what has no AWS counterpart.
Need to ship this week — Deployment first — particularly the note on why
azurerm_app_configuration_key needs a data-plane role assignment that doesn't exist yet when the
plan runs — then the security and cost sections of Production.
Doing feature flags properly — the feature-flag and variant sections of Core Concepts, then the client-library and refresh sections of Architecture, then Integrations for how the flag reaches a container or a browser.
Debugging "it's reading the wrong value" — the label-selection and caching sections of Architecture. It is almost always a label filter, a cached value that hasn't expired, or a sentinel key nobody updated.
Chasing a bill or a 429 — the cost and scaling sections of
Production. It is almost always a client polling too aggressively, a
per-request read that should have been a startup read, or an unnoticed second replica.
Interview or certification prep — Core Concepts, Architecture, and Interview Questions. The control-plane-versus-data-plane question, the Key-Vault-reference question, and the sentinel-key question come up constantly.
Next: What & Why →