Environment variables & secrets
What environment variables are, where secrets should live, how to rotate them, and why they must never be committed to a Git repository.
- Difficulty
- Intermediate
An application needs to know things it must never publish: the database password, the payment provider's secret key, the token for its email service. Those values are supplied as environment variables — configuration handed to the app at runtime rather than written into its code.
Quick summary
Environment variables keep secrets out of your source code. They are set in your hosting platform's dashboard (Vercel, Render, AWS, and so on), separately for each environment — on Vercel, for example, that's production, preview and development, plus any custom environments you add on a paid plan. A secret committed to Git must be treated as compromised and rotated, even if you delete it afterwards.
Why they exist
Two reasons, and both matter:
- Security. Source code gets copied, forked, shared with contractors, and occasionally made public by accident. Configuration handed in at runtime doesn't travel with it.
- Environments. The same code needs to point at a test database in staging and the real one in production. Changing a variable is safer than changing code.
Public vs secret variables
Not every environment variable is a secret, and the distinction is easy to get wrong.
| Type | Visible to | Examples |
|---|---|---|
| Public | Anyone who views your site | Analytics IDs, publishable API keys, price identifiers, public URLs |
| Secret | Server only | Database passwords, secret API keys, signing secrets, webhook secrets |
Framework prefixes make variables public
Many frameworks expose variables to the browser when they carry a specific
prefix — NEXT_PUBLIC_, VITE_, REACT_APP_, EXPO_PUBLIC_ and similar.
Each of those frameworks writes the value straight into the JavaScript bundle
at build time, so anyone can read it by inspecting your site's files. Anything
with one of those prefixes is not a secret, no matter where you stored it.
Putting a secret key behind a public prefix is one of the most common ways
credentials leak.
Payment providers make this distinction explicit: a publishable key is designed to sit in the browser, while a secret key must stay on the server. Both are needed; only one is safe to expose.
Where secrets should live
In your hosting platform's dashboard. Vercel, Render and equivalents all let you store environment variables in the platform instead of in your code, set separately per environment. This is the default answer. Vercel goes a step further: a variable saved as a Secret becomes write-only afterwards, so nobody can read the value back out of the dashboard.
In a dedicated secrets manager for larger setups — AWS Secrets Manager, or AWS Systems Manager Parameter Store for plainer configuration. Worth it when you need audit logs and automated rotation. AWS's own docs point you at Secrets Manager rather than Parameter Store for credentials, API keys and tokens.
In a password manager for the human copy. Someone needs to be able to recover a value that only ever existed in a dashboard. See using a password manager.
Locally, in a .env file that is never committed. Every project should
list .env in .gitignore and ship a .env.example containing the names
of required variables with empty or dummy values.
What never belongs in Git
Not in the code, not in a config file, not in a comment, not in a commit message, and not in the repository's history.
Deleting a committed secret does not undo it
Git keeps history. A key pushed and then removed in a later commit is still retrievable from the repository, from every clone, and often from forks and CI logs. Automated scanners hunt for exposed credentials in public code. The only real fix is to rotate the secret — issue a new one and invalidate the old. Cleaning history is worth doing afterwards, but rotation comes first.
Rotating secrets
Rotation means replacing a credential with a new one and retiring the old. Do it:
- When someone with access leaves — see team offboarding security
- When a secret has been exposed, or you aren't certain it hasn't
- When ending a working relationship with an agency or contractor
- On a schedule, for high-value credentials
The safe order avoids downtime:
Common questions
Do I need to redeploy after changing a variable?
Usually yes. Most platforms bake environment variables in at build or boot time, so an existing running instance keeps the old value until it restarts or redeploys. If a change appears to have no effect, this is the first thing to check.
Can you see our secrets?
Anyone with dashboard access to an environment can generally read or replace its variables — that's what the access is for. Some platforms mark values write-only after saving. If you'd rather we never see production secrets, we can work against a staging environment and have someone on your side set the production values.
What's the difference between a secret key and a webhook secret?
A secret key authenticates you to a service. A webhook secret lets you verify that an incoming request genuinely came from that service. Both are secrets; they protect opposite directions of the conversation.
Should staging and production share credentials?
No. Separate credentials mean a mistake in staging can't touch live data or charge a real customer. Payment providers supply distinct test and live keys precisely for this.
Related guides
Need a hand?
Learn more
Last updated
Developer platforms & services → start here
Reference guides for the hosting, cloud, and developer services behind custom applications — access, roles, secrets, and ownership.
Vercel access & project ownership
How Vercel teams and roles work, how to invite people, where environment variables live, and how to transfer a project you own.