๐ WAYPOINT LESSON
Environment-Specific Config and Secrets
โญโญ intermediateโณ 15 min read๐ Lesson 124 of 265
Dev/staging/prod differences, layered lookup, and the never-commit-a-secret discipline.
Environments differ by wiring, not by code
The same binary runs in dev (local DB, verbose logging), staging (prod
shape, test data), production (real DB, sampled logging). The ENVIRONMENT
NAME selects which config layer loads โ code never branches on
if (env == "prod") for business behavior.
Layered lookup
string? Get(string key) =>
Environment.GetEnvironmentVariable(Prefix + key) // 1. env
?? FromJson(key) // 2. appsettings.json
?? Defaults(key); // 3. code defaults
Order matters and stays the same everywhere; production overrides staging overrides dev only through SOURCES, never through code paths.
Secrets: the discipline
API keys, connection passwords, signing keys:
- NEVER in source or Git history โ "we'll rotate before merging" is how breaches happen. Assume anything committed is burned forever.
- Secrets come from the environment or a secret store (env vars for this course; user-secrets tooling / vaults in real deployments).
- NEVER log them โ a request log that echoes an Authorization header is a leak. Log key NAMES, never values.
- No hardcoded fallbacks:
config["ApiKey"] ?? "sk-dev-123"silently ships a credential.
Check your understanding
- Where does "which DB is the staging one" live? (Staging's config source โ not an if in code.)
- Why is a hardcoded default for a secret worse than throwing? (It silently ships a real credential; failing fast surfaces the misconfiguration.)
โก Now practice
Ready to CodeConfig Practice: Providers, Binding, SecretsBuild an environment provider, bind JSON into typed options, and close the hardcoded-secret hole.
3 challenges ยท ยท ~30 min