Ensuring the Same Configuration Across Development, QA, and Production
One of the biggest deployment challenges is making sure the application behaves consistently across all environments while allowing environment-specific settings (like connection strings and API keys).
1. Keep Configuration Outside the Code (12-Factor App)
Never hardcode environment-specific values.
Bad
var connectionString = "Server=DEV-SQL;Database=MyApp;";
Good
builder.Configuration.GetConnectionString("DefaultConnection");
Store values in configuration files, environment variables, or a secret manager.
2. Use Environment-Specific Configuration Files
ASP.NET Core supports this automatically.
appsettings.json
appsettings.Development.json
appsettings.QA.json
appsettings.Production.json
Example:
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
appsettings.Production.json
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
}
}
3. Use Environment Variables for Sensitive Data
Never store:
- Database passwords
- API Keys
- JWT Secret
- Payment secrets
Instead:
ConnectionStrings__Default
JWT__Secret
Stripe__SecretKey
Environment variables override appsettings values.
4. Keep the Same Infrastructure as Much as Possible
Try to keep:
- Same .NET version
- Same OS
- Same Docker image
- Same IIS/Kestrel version
- Same database version
- Same Redis version
Only change what must differ (URLs, credentials, scaling).
5. Infrastructure as Code (IaC)
Provision environments using tools such as:
- Terraform
- Bicep
- ARM Templates
- AWS CloudFormation
This ensures infrastructure is reproducible and consistent.
6. Use Docker
Package the application once.
FROM mcr.microsoft.com/dotnet/aspnet:8.0
Deploy the same image to:
- Development
- QA
- Production
Only inject different configuration values through environment variables.
7. CI/CD Pipeline
Build once.
Developer
↓
Build
↓
Run Tests
↓
Create Artifact
↓
Deploy to Dev
↓
Deploy Same Artifact to QA
↓
Deploy Same Artifact to Production
Don't rebuild for each environment. Promote the same artifact to reduce inconsistencies.
8. Database Migration Strategy
Use migration tools consistently.
dotnet ef database update
Or execute migrations during deployment.
Every environment should have:
- Same schema
- Same indexes
- Same stored procedures
9. Validate Configuration at Startup
Fail fast if required settings are missing.
builder.Services
.AddOptions<JwtOptions>()
.BindConfiguration("JWT")
.ValidateDataAnnotations()
.ValidateOnStart();
This prevents the application from starting with invalid configuration.
10. Automated Testing
Before promoting to Production:
- Unit Tests
- Integration Tests
- API Tests
- Smoke Tests
- Health Checks
These help verify that the application behaves consistently across environments.
11. Feature Flags
Instead of maintaining different codebases:
Production
Feature A = ON
Feature B = OFF
QA
Feature A = ON
Feature B = ON
The code remains the same; only feature toggles change.
12. Configuration Validation in CI/CD
The pipeline should verify:
- Required environment variables exist
- Secrets are available
- Connection strings are valid
- Configuration files are syntactically correct
This catches issues before deployment.