Database passwords, API keys, and similar credentials need to exist somewhere for a live site to function — this lesson covers where they actually go, and why the wrong answer is a serious, common mistake.
Code is typically stored in a Git repository, and if that repository is ever pushed to a public host, made public later, or simply read by anyone with access, any credential written directly into it is exposed — permanently, since old commits remain in Git's history even after the line is later deleted. This is a genuinely common real-world mistake, not a hypothetical one.
An environment variable is a named value supplied to a running program by its surrounding environment (the operating system or hosting platform) rather than written into the code itself. The code reads a name like DATABASE_PASSWORD and receives whatever value the environment has for it — the actual value lives entirely outside the codebase.
# The code never contains the actual password —
# only the name of a variable it expects to find:
DATABASE_URL=$DATABASE_URL
API_KEY=$STRIPE_SECRET_KEY| Setup | Where secrets live |
|---|---|
| Cloud and managed platforms | A dedicated "Environment Variables" section in the project dashboard, set per-environment (production, staging, preview) |
| A traditional server (VPS, shared hosting) | A local .env file on the server itself, or the control panel's own environment-variable settings, kept out of the Git repository |
| Local development | A .env file on your own machine, containing test or placeholder values, never committed |
A .env file holding real secrets must be listed in .gitignore so Git never tracks it in the first place — the platform-level environment variables above are what actually reach the live server; the local .env file is only for your own machine and must never be pushed alongside the code.
A leaked secret must be rotated, not just removed
If a real credential is ever accidentally committed to Git, changing the code afterward is not enough — the credential itself must be rotated (changed at the source, such as regenerating an API key), because the old value remains permanently visible in the repository's history regardless of later edits.