Managing Production Configurations in ASP.NET Core Web API Using Environment Variables
Production configuration should be dynamic, secure, and deployment-friendly. ASP.NET Core already gives a strong configuration pipeline that lets you override settings cleanly without changing code.
This guide explains how to use environment variables with appsettings files for real production workflows.
Why It Matters
- Keeps secrets out of source code.
- Allows runtime config updates per environment.
- Works naturally with Docker, Kubernetes, and cloud platforms.
- Reduces risky manual edits in production.
Core Concepts
1. ASP.NET Core Configuration Sources
ASP.NET Core merges config from multiple providers.
Typical order (low to high priority):
- Default values in code
appsettings.jsonappsettings.{Environment}.json- Environment variables
- Command-line arguments
2. Environment-Specific appsettings Files
ASPNETCORE_ENVIRONMENT controls environment-specific file loading.
If:
ASPNETCORE_ENVIRONMENT=Production
Then appsettings.Production.json is loaded automatically and merged.
3. Environment Variable Override Pattern
Use __ (double underscore) for nested keys.
- JSON key:
AppSettings:ApiUrl - Env var:
AppSettings__ApiUrl
4. Example Configuration Merge
Base config:
{
"AppSettings": {
"ApiUrl": "https://api.default.com",
"ApiKey": "default-api-key"
}
}
Production override:
{
"AppSettings": {
"ApiUrl": "https://api.production.com"
}
}
Environment variables:
AppSettings__ApiUrl=https://api.override.com
AppSettings__ApiKey=override-api-key
Final result at runtime:
-
ApiUrl:https://api.override.com -
ApiKey:override-api-key
5. Strongly Typed Options
Bind config sections into typed options.
public sealed class AppSettingsOptions
{
public string ApiUrl { get; set; } = string.Empty;
public string ApiKey { get; set; } = string.Empty;
}
builder.Services
.AddOptions<AppSettingsOptions>()
.Bind(builder.Configuration.GetSection("AppSettings"))
.ValidateDataAnnotations()
.ValidateOnStart();
6. Secure Secret Management
Use platform secret stores for sensitive values in production.
Practical Example
Docker Compose
services:
webapi:
image: yourapp:latest
environment:
- ASPNETCORE_ENVIRONMENT=Production
- AppSettings__ApiUrl=https://api.docker.com
- AppSettings__ApiKey=docker-api-key
ports:
- "5000:80"
Using .env file:
services:
webapi:
image: yourapp:latest
env_file:
- .env
ports:
- "5000:80"
Kubernetes
ConfigMap for non-sensitive values:
apiVersion: v1
kind: ConfigMap
metadata:
name: appsettings-config
data:
AppSettings__ApiUrl: https://api.k8s.com
Secret for sensitive values:
apiVersion: v1
kind: Secret
metadata:
name: appsettings-secret
type: Opaque
data:
AppSettings__ApiKey: a3BpLXZhbHVlCg==
Deployment injection:
envFrom:
- configMapRef:
name: appsettings-config
- secretRef:
name: appsettings-secret
If configuration is correct, deployment changes become config operations, not emergency redeploy events.
Common Mistakes
- Committing secrets into
appsettings.json. - Forgetting
__for nested environment variable keys. - Skipping startup validation for required config values.
- Mixing sensitive and non-sensitive values in same storage.
- Assuming local environment behavior matches production.
Quick Recap
- Use
appsettings.jsonfor defaults. - Use
appsettings.{Environment}.jsonfor environment-level overrides. - Use environment variables for final runtime control.
- Validate critical settings at startup.
- Store secrets in proper secret managers.
Next Steps
- Add config health check endpoint for required keys.
- Integrate cloud secret manager (Key Vault/Secrets Manager).
- Add CI validation for missing environment variables.
- Use tooling like
dotnet-appsettings-envto generate env mappings faster.
Top comments (0)