Vercel

Environment Variables And Secrets

Environment Variables let you configure a Vercel project without hard-coding every value in source code. They are used for API keys, database URLs, feature flags, webhook secrets, service endpoints, email settings, analytics IDs, and environment-specific behavior. Used well, they keep a project portable and keep sensitive values out of Git. Used carelessly, they can expose secrets to the browser, leak through logs, or make preview deployments affect production systems.

The core rule is simple: configuration belongs outside source code when it changes between environments or contains secrets. Your repository should describe what variables the app expects, but it should not contain production credentials. Vercel provides project-level Environment Variables that can be scoped to environments such as Production, Preview, and Development.

This lesson is not about memorizing every Vercel dashboard option. It is about forming safe habits: name variables clearly, scope them intentionally, avoid committing .env files, keep browser-exposed values separate from server-only secrets, and rotate credentials when they may have leaked.

What Environment Variables Are

An environment variable is a named value supplied by the execution environment. Application code reads the value at build time or runtime instead of hard-coding it.

A server-side function might read:

const apiKey = process.env.EMAIL_API_KEY;

A build process might read:

const apiBaseUrl = process.env.API_BASE_URL;

The code names the variable. The environment supplies the value. That separation lets the same repository deploy to preview and production with different settings.

For example:

Variable name: EMAIL_API_KEY
Preview value: test_email_key_123
Production value: live_email_key_456

The source code stays the same. The deployment environment changes the value.

Secrets Do Not Belong In Git

A secret is any value that gives access to something private or costly. API keys, database passwords, webhook signing secrets, OAuth client secrets, private tokens, service-account JSON, SMTP passwords, and encryption keys are secrets.

Do not commit secrets to the repository:

Do not commit:
- .env
- .env.local
- production database dumps
- service-account JSON files
- private certificates
- API keys copied into JavaScript
- screenshots showing credentials

A private GitHub repository is still not a secret store. Collaborators, CI systems, deployment integrations, local clones, logs, backups, and future access changes can all expose repository contents. If a secret is committed, assume it may need rotation even if you delete it later. Git history can preserve the old value.

Instead, store secret values in Vercel Environment Variables or in an approved secret-management system for the project.

Production, Preview, And Development Values

Vercel lets projects use different values for different environments. That is essential for safe deployment.

A project might use:

Development
  DATABASE_URL=local database
  EMAIL_API_KEY=fake or sandbox key

Preview
  DATABASE_URL=preview database
  EMAIL_API_KEY=test provider key

Production
  DATABASE_URL=production database
  EMAIL_API_KEY=live provider key

Do not use production services in Preview by default. Preview branches are experimental. They may include unfinished code, unreviewed form handling, temporary logging, broken authorization, or test flows. A preview should not charge real customers, send real transactional email, update production records, or call paid third-party APIs at full scale unless the team has explicitly designed it that way.

Development values should be easy to replace. A new developer should be able to read documentation, create local variables, and run the app without asking someone to paste production secrets into chat.

Document The Expected Variables

The repository should document variable names without exposing real values. A common pattern is an example file:

.env.example

It might contain safe placeholders:

EMAIL_API_KEY=replace-with-provider-key
CONTACT_TO_ADDRESS=you@example.com
PUBLIC_SITE_NAME=My Test Site

The real .env file should be ignored by Git. The example file is committed so developers and deployers know what to configure.

For Vercel projects, a useful deployment note can be:

Required Vercel Environment Variables:
- EMAIL_API_KEY: server-side only, Preview and Production values differ
- CONTACT_TO_ADDRESS: server-side only
- PUBLIC_SITE_NAME: safe to expose in browser output

Notice that the documentation says which values are server-side only. That label helps reviewers catch unsafe frontend usage.

Browser-Exposed Variables Are Public

Frontend frameworks often have a naming convention for variables that should be included in browser JavaScript. In Next.js, variables prefixed with NEXT_PUBLIC_ are intended for browser exposure. Other frontend tools have their own conventions, such as VITE_ in Vite.

The exact prefix depends on the framework. The security rule does not: anything shipped to browser JavaScript is public. A visitor can inspect JavaScript bundles, network requests, source maps, page markup, and runtime state. If a key must remain secret, do not expose it to the browser.

Safe public values might include:

NEXT_PUBLIC_SITE_NAME=Acme Docs
NEXT_PUBLIC_ANALYTICS_ID=public analytics identifier
VITE_PUBLIC_API_BASE=https://api.example.com

Unsafe public values include:

NEXT_PUBLIC_STRIPE_SECRET_KEY=...
NEXT_PUBLIC_EMAIL_API_KEY=...
VITE_DATABASE_PASSWORD=...
VITE_ADMIN_TOKEN=...

The word PUBLIC is not magic protection. It is a warning label: this value can end up in code users download.

Use Server-Side Code For Private API Calls

If a frontend needs to call a private API, do not put the private key in browser JavaScript. Use a server-side boundary such as a Vercel Function or framework API route.

The safe shape is:

Browser
  sends normal form data to /api/contact

Vercel Function
  validates the request
  reads EMAIL_API_KEY from server-side environment
  calls email provider
  returns a safe response

Email provider
  receives request from server-side code

The unsafe shape is:

Browser
  downloads EMAIL_API_KEY
  calls email provider directly

The unsafe shape lets anyone reuse the key. They can send spam, read data, create charges, or exhaust usage limits depending on the service. Server-side code does not remove every risk, but it gives you a place to validate input, rate-limit, hide credentials, and log behavior.

Sensitive Variables And Access

Vercel supports sensitive environment-variable handling for values that should have stronger protection. Use sensitive variables for real secrets where available and appropriate. The exact dashboard behavior can change, so check the current Vercel documentation before relying on a particular access or reveal workflow.

Even with sensitive variables, access control matters. Someone who can change project settings, deploy code, or read logs may still be able to influence how secrets are used. Do not give broad project access just because the variable value is hidden in the dashboard.

Treat production secrets as production infrastructure:

Only needed people can edit them.
Changes are reviewed or at least recorded.
Preview and production values are separate.
Rotation steps are known.
Logs do not print the values.
Old developers and contractors lose access when work ends.

For client work, the client organization should own the Vercel team and production secrets. A contractor should not be the permanent holder of another business's production credentials.

Build-Time Vs Runtime Use

Some environment variables are read during build. Others are read when a request runs. The distinction matters because a value used during build may be baked into generated files.

For example, a static frontend might read PUBLIC_SITE_NAME during build and write it into HTML. Changing the variable later may require a new deployment before the site changes.

A serverless function might read EMAIL_API_KEY at runtime. Changing that variable may affect future function executions after redeployment or according to platform behavior. Do not assume every variable update affects already-built files instantly.

A practical habit is to redeploy after changing deployment-critical variables, then verify the behavior in the environment you changed.

Local Development And .env Files

Local development often uses .env files. These files are convenient, but they are also easy to commit by accident. Add local environment files to .gitignore before putting real values in them.

A safe local pattern is:

.env.example   committed, placeholders only
.env.local     ignored, real local values

Do not share .env.local through chat, screenshots, pull requests, or issue comments. If someone needs access, use the project's approved secret-sharing process. For a course exercise, use fake values whenever possible.

The Vercel CLI can help pull configured environment variables for local use in some workflows. That can be convenient, but it also means local machines may receive real secrets. Use it deliberately and protect the local files it creates.

Debugging Missing Or Wrong Variables

When a deployment behaves as if a variable is missing, check the environment first instead of rewriting application code. Confirm the variable name exactly, including capitalization and underscores. Environment variable names are case-sensitive in many runtimes, so EMAIL_API_KEY and Email_API_Key are different names. Next confirm that the value exists in the environment where the problem happens. A variable set only for Preview will not automatically be available in Production, and a local .env value does not prove the hosted deployment has the same value.

Also confirm when the app reads the value. If the value is used during build, changing it in the dashboard may require a new deployment before generated files change. If the value is used inside a server-side function, verify the function was redeployed and that the code reads the correct name. Avoid debugging by printing the whole secret. Log only safe facts such as EMAIL_API_KEY is configured: yes, never the value itself.

When values differ between environments, write the expected behavior down. A preview deployment should often call sandbox services, while production should call live services. If both environments accidentally use the same credential, you have not separated risk; you have only moved the secret out of Git.

Rotating Secrets

A secret should be rotated when it may have leaked, when a person with access leaves, when a provider recommends rotation, or when a scheduled security process requires it. Rotation means creating a new credential, updating the environment variable, redeploying or restarting as needed, verifying the app works, and disabling the old credential.

A simple rotation checklist is:

Create new provider credential.
Add new value to Vercel Environment Variables.
Redeploy affected environments.
Verify the app works.
Disable old credential.
Check logs for errors.
Record the rotation.

Do not delete the old credential first unless you are prepared for downtime. For some providers, both old and new credentials can overlap briefly. For others, rotation must be carefully sequenced.

Common Mistakes

The first mistake is committing .env files. Add ignore rules before storing real local secrets.

The second mistake is prefixing a secret with a public frontend prefix. Public variables are not hidden from users.

The third mistake is using production credentials in Preview. A branch deployment should not casually touch real payment, email, or database systems.

The fourth mistake is printing environment variables in logs while debugging. Logs may be visible to teammates or retained by the platform.

The fifth mistake is documenting only variable names without purpose. Future maintainers need to know whether a value is public, server-only, preview-only, or production-critical.

The sixth mistake is assuming deleting a leaked value from Git is enough. Rotate the credential and remove it from history where appropriate.

Review Questions

  • Why should production secrets stay out of Git?
  • What is the difference between Preview and Production environment-variable values?
  • Why are NEXT_PUBLIC_ style variables unsafe for secrets?
  • When should a frontend call a server-side function instead of a private API directly?
  • What should an .env.example file contain?
  • What steps belong in a secret rotation checklist?

Official References