5.1.6. Design Application Configuration and Automated Deployment
💡 First Principle: Code, configuration, secrets and infrastructure change at different rates and carry different risks. Code changes per release; configuration changes per environment, sometimes per hour; secrets must rotate without anyone reading them; infrastructure should change only through a reviewed plan. When all four ship in one package, every settings tweak becomes a redeployment and every redeployment risks the secrets. Separate them and each can move at its own speed.
Scenario: A SaaS provider runs 40 instances of its API across two regions. Operations wants to change throttling settings without redeploying, product wants to expose a new checkout flow to a beta group and then 10% of users, security forbids secrets in configuration stores and long-lived credentials in CI/CD, and the change board wants to see exactly which Azure resources a release will modify before approving it.
Where each kind of setting belongs:
| Store | Holds | Why |
|---|---|---|
| Azure App Configuration | Settings and feature flags shared by many apps, environments and regions | Central, labeled, refreshable without redeploying (What is App Configuration?) |
| Azure Key Vault | Secrets, keys, certificates | Hardware-level encryption, granular access policies, rotation — Microsoft still names Key Vault the best place for secrets (App Configuration FAQ) |
| App Service app settings | Per-app values passed as environment variables, optionally slot-specific | Simple for one app; not shared across apps |
Key Vault references connect the two without mixing them. An App Configuration Key Vault reference stores a URI, not the secret. The client provider sees the reference and reads the secret directly from Key Vault — App Configuration never accesses the vault, so the application's identity needs rights on both services (Key Vault references). App Service has its own form, @Microsoft.KeyVault(SecretUri=...), resolved with the app's managed identity; a versionless reference picks up a rotated secret within 24 hours (App Service Key Vault references).
Design decisions in App Configuration:
| Decision | Recommendation |
|---|---|
| Separate environments | A separate store per environment when permissions must differ — access is controlled per store. Use labels only when isolation is not needed |
| Change settings without restarts | Providers poll a sentinel key and reload when it changes; feature flags are monitored separately |
| Release features independently of deployment | Feature flags with the targeting filter (named users and groups plus a percentage), time window filter, or variants |
| Promote a known-good configuration | Snapshots — named, immutable sets of key-values; the app references a snapshot by name, and rollback means pointing back to the last known good one (Snapshots) |
| Regional resilience | Geo-replication (Standard and Premium tiers) |
Tier choice (App Configuration FAQ):
| Tier | SLA | Request quota | Notable |
|---|---|---|---|
| Free | None | 1,000 per day | Evaluation only |
| Developer | None | 6,000 per hour | Private Link; non-production |
| Standard | 99.9% (99.95% with geo-replication) | 30,000 per hour | Private Link, customer-managed keys, soft delete, geo-replication |
| Premium | 99.9% (99.99% with geo-replication) | No request quota | Includes a replica; highest throughput |
Automated deployment: the infrastructure half. Section 1.6 compared the tools; the design questions here are how a pipeline uses them safely.
| Concern | Recommendation |
|---|---|
| Azure-native IaC | Bicep (compiles to ARM JSON). Run what-if to preview Create, Modify and Delete changes before deploying — it changes nothing (What-if) |
| Multicloud IaC | Terraform — store state remotely in an Azure Storage blob container, which is locked before every state write; state is plain text and can contain secrets, so restrict access to that account (Terraform state in Azure Storage) |
| Manage and protect an environment as one unit | Deployment stacks with deny settings — see 2.1.1.2; what-if can preview stack changes too |
| Pipeline credentials | OpenID Connect workload identity federation: a federated credential on a Microsoft Entra application or user-assigned managed identity trusts the pipeline's tokens, so no client secret is stored (GitHub Actions with OIDC) |
| Production approval | Gate the production job on an environment with required reviewers, and show them the what-if output |
The application half combines the pieces above: build once, deploy the same artifact to each environment, use deployment slots to warm and swap (see 5.1.1.2), and use feature flags so that deploying code and releasing a feature are separate decisions.
⚠️ Exam Trap: "Grant the App Configuration store's managed identity access to Key Vault so it can resolve references." App Configuration and Key Vault never talk to each other. The application's identity needs a read role on the store and Key Vault Secrets User (or Get permission) on the vault.
⚠️ Common Pitfall: Treating what-if as a guarantee. It cannot evaluate nondeterministic functions such as utcNow(), references to secure parameters, or resources not defined in the same template, and it reports Delete only for complete-mode JSON deployments. Read it as a review aid, not as proof.
Key Trade-Offs:
- Central configuration vs dependency: App Configuration removes redeploys for settings changes, but the store becomes a runtime dependency — tier, request quotas and geo-replication must be sized like any other production service.
- Bicep vs Terraform: Bicep needs no state file and sees new Azure features first; Terraform spans clouds at the cost of state you must store, lock and protect.
Reflection Question: In the SaaS scenario, which of the five requirements does each of App Configuration, Key Vault, feature flags, what-if and workload identity federation satisfy — and which requirement would still be unmet if you used App Service app settings alone?