Environment Configuration and Safe Logging
Configuration belongs outside your code, not hardcoded inside it — and logs are a real, common place secrets accidentally leak.
What you'll learn
- Explain why configuration values belong in environment variables, not hardcoded in source
- Write a function that redacts sensitive fields before logging
- Identify which fields are sensitive and should never appear in a log
Prerequisites
Explanation
A database connection string, an API key, a port number — none of these belong hardcoded directly in source code. Configuration should come from the environment (process.env.DATABASE_URL, conventionally loaded from a .env file in local development, and from the real hosting platform's environment variable settings in production) for two concrete reasons: it lets the same code run correctly against different databases/settings in development, testing, and production without any code change, and it keeps genuine secrets (API keys, database passwords) out of version control entirely — a secret hardcoded in source code is a secret that's now in the project's Git history forever, even if it's later removed from the current file.
Logging is a real, common, easy-to-overlook place secrets leak. A request-logging middleware that logs "the full request body, for debugging" will happily log a user's password field on every failed login attempt, or a credit card number, straight into a log file or logging service — often one with broader access than the database itself, and frequently retained far longer. Safe logging means explicitly redacting known-sensitive fields before anything is written — password, token, apiKey, ssn, creditCard, and any project-specific sensitive field — replacing their value with a fixed placeholder like "[REDACTED]" rather than logging them verbatim, and doing this centrally (one logging utility every part of the codebase uses) rather than hoping every individual log statement remembers to do it correctly.
This connects directly to the error-handling lesson: a caught error object sometimes contains the very request data that triggered it, including sensitive fields — logging console.error(err) naively, where err happens to carry the original request body, can leak exactly the same sensitive data a careless request logger would. The discipline is the same everywhere data might be written to a log: redact known-sensitive fields first, always, centrally.
Example
A real redaction function, applied before logging -- the exact utility a safe logging setup uses everywhere data is written out.
const SENSITIVE_FIELDS = ["password", "token", "apiKey", "creditCard", "ssn"];
function redact(obj) {
const copy = { ...obj };
for (const field of SENSITIVE_FIELDS) {
if (field in copy) copy[field] = "[REDACTED]";
}
return copy;
}
const loginAttempt = { email: "ada@example.com", password: "hunter2" };
console.log("Raw (never log this):", loginAttempt);
console.log("Safe to log:", redact(loginAttempt));Try it yourself
Add 'apiKey' to a new test object and confirm redact() masks it correctly.
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Guided exercise
Guided exercise
Using redact and SENSITIVE_FIELDS already defined, redact a request body containing email, password, AND a nested field 'note' that mentions a password in plain text (this exercise only requires redacting top-level fields, not the note text itself). Confirm password is redacted but email and note pass through unchanged.
Checks: redacts the password field · leaves a non-sensitive field unchanged
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Stuck? Get a hint.
Independent exercise
Independent exercise
Write readConfig(env, key, required) that reads env[key] (simulating process.env). If the value is missing and required is true, throw an Error naming the missing key. If missing and required is false, return undefined. Otherwise return the value.
Checks: returns a present required value · throws a clear error for a missing required value · returns undefined for a missing optional value
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Stuck? Get a hint.
Common mistakes
- Hardcoding a database URL, API key, or other configuration value directly in source code instead of reading it from an environment variable.
- Logging an entire request body or error object verbatim without redacting known-sensitive fields first.
- Committing a real .env file (with actual secret values) to version control instead of only a `.env.example` template with blank or placeholder values.
Knowledge check
Takeaway
Configuration belongs in environment variables, not hardcoded in source, and logging must redact known-sensitive fields centrally — logs are a real, common, easy-to-overlook place secrets leak.
Summary
This lesson covered why configuration should be environment-driven rather than hardcoded, and built a real redaction function for safely logging data that might contain sensitive fields.
References
Your notes
Notes save automatically.
Finished this lesson?
Mark it complete to track your progress and schedule a future review.
AI tutor
The optional AI tutor isn't enabled in this deployment. All lessons, exercises, quizzes, and search work fully without it.