Overview
Vercel environment variables are stored encrypted and injected at build time or runtime depending on when they are read. The platform provides three environments (Development, Preview, Production), per-variable sensitivity settings, and a CLI command to pull vars locally. Misscoped variables are the most common source of preview-to-production data leakage and of missing-variable build failures. This page covers correct scoping, the build-vs-runtime distinction, and the patterns that keep secrets safe.
Set every variable for the narrowest environment that needs it
The three Vercel environments are mutually exclusive scopes. A variable set on Production does not appear in Preview, and vice versa. Assign each variable to exactly the environments where it should exist.
| Variable | Development | Preview | Production |
|---|---|---|---|
DATABASE_URL | local URL | staging URL | prod URL |
STRIPE_SECRET_KEY | test key | test key | live key |
NEXT_PUBLIC_API_URL | http://localhost:3001 | preview API | prod API |
SENTRY_DSN | (unset or test) | staging DSN | prod DSN |
Never set DATABASE_URL to the production value on Preview. A bad migration or an accidental delete query on a preview build should hit the staging database. See vercel-preview-deployments for the full argument for preview isolation.
Mark secrets as sensitive to prevent log exposure
In the Vercel dashboard, variables can be flagged as sensitive. Sensitive variables are encrypted at rest and never exposed in the dashboard after creation. They are also redacted from build logs.
Mark as sensitive:
- API keys and secrets
- Database URLs (contain credentials)
- JWT signing secrets
- OAuth client secrets
- Any value that begins with a protocol and contains credentials (
postgres://user:password@...)
Variables that are not sensitive (public API base URL, feature flag config, analytics measurement ID) do not need the sensitive flag. The flag is not binary security; it is a leak-prevention layer. Do not rely on it as the sole control for production credentials. See security for the wider secrets management rules.
Distinguish NEXT_PUBLIC_* (build-time, client-visible) from runtime-only variables
In Next.js, variables prefixed with NEXT_PUBLIC_ are inlined at build time into the JavaScript bundle. They are visible in the browser. Use this prefix only for values that are safe to expose publicly.
NEXT_PUBLIC_ANALYTICS_ID=G-XXXXXXXXXX # OK: public, no auth capability
NEXT_PUBLIC_API_URL=https://api.example.com # OK: no credentials
DATABASE_URL=postgres://... # Never use NEXT_PUBLIC_ here
STRIPE_SECRET_KEY=sk_live_... # Never use NEXT_PUBLIC_ hereRuntime-only variables (no NEXT_PUBLIC_ prefix) are available in server components, API routes, and server actions. They are never inlined into the bundle. A secret accidentally prefixed with NEXT_PUBLIC_ exposes it to every user who opens the browser dev tools. See nextjs for the server-component boundary where runtime vars are safe to use.
Pull vars locally with vercel env pull
Keep local development in parity with the Vercel environment by pulling the Development-scoped variables into .env.local:
vercel env pull .env.localThis overwrites .env.local with the current Development-scoped values. Add .env.local to .gitignore (Next.js does this by default). Never commit .env.local or any .env file that contains real credentials.
Run this command whenever a variable changes in the Vercel dashboard. Local development that diverges from the Vercel Development scope is the source of “works locally, fails on preview” bugs.
Add variables via the CLI for automation and reproducibility
The Vercel dashboard is convenient for one-off changes. For project setup, secret rotation, and CI provisioning, use the CLI to keep changes auditable.
# Add a variable to Production only
vercel env add DATABASE_URL production
# Add a variable to Preview and Development
vercel env add STRIPE_TEST_KEY preview development
# List all variables (shows names, not values)
vercel env lsFor sensitive secrets, prefer the dashboard or the CLI over infrastructure-as-code tools that store plain-text values in YAML. Terraform’s Vercel provider can manage env vars, but it stores values in Terraform state, which must itself be encrypted and access-controlled. See cloudflare for a comparison with Cloudflare’s secrets model.
Rotate secrets without downtime using overlapping deployments
When rotating a secret (API key, database password), add the new value and redeploy before revoking the old one. Vercel deployments are immutable: the current production deployment continues to use the old value until a new deploy promotes the new one.
The rotation sequence is:
- Create the new credential in the upstream service.
- Update the Vercel variable with the new value.
- Trigger a new deploy and verify it succeeds.
- Revoke the old credential.
Revoking before the new deploy is live causes a production outage if the deploy takes longer than expected. The overlap window is typically minutes. See vercel for the immutable deployment model.