---
title: How to add and manage environment variables on Vercel
description: Add environment variables to Vercel through the dashboard, CLI, or REST API, scope them to each environment, and pull them into local development.
url: "https://vercel.com/kb/guide/how-to-add-vercel-environment-variables"
published: 2026-07-27
last_updated: 2026-09-10
authors: Vercel
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

You add an [environment variable](https://vercel.com/docs/environment-variables) to a Vercel project in the dashboard, with the Vercel CLI, or through the REST API. Whichever method you use, the change takes effect on your next deployment, not on the deployment that's already live. After adding a variable, you choose its type (Config or Secret), scope it to Production, Preview, Development, or a custom environment, then pull the same values into local development so every environment runs the same configuration.

This guide covers each method, how types and scoping work, and the handful of behaviors that cause most environment variable bugs.

## Adding environment variables to your project

All three methods write to the same underlying store, so you can mix manual edits in the dashboard with automation without changing how deployments read the values. Start with the method that fits where the work belongs.

### Add variables in the dashboard

Open your project in the [Vercel dashboard](https://vercel.com/dashboard) and go to Environment Variables, add a key and value, and select the environments the variable applies to. Vercel encrypts values at rest. When you add a variable, choose its type: Config values stay readable to members with access, while Secret values are write-only after saving and can't be viewed or retrieved. For Secrets, you can assign a different value per environment or Preview branch, and the environment variable table shows a Config or Secret label next to each entry.

You can also create variables at the team level by opening Environment Variables from the team sidebar; both project and [shared environment variables](https://vercel.com/docs/environment-variables/shared-environment-variables) support the Config and Secret types.

Integrations like Neon, Supabase, and Upstash add their own variables to your project settings, with the integration name shown next to each one. When you migrate from another platform, add variables in bulk instead of one at a time by pasting the contents of a `.env` file or uploading the file directly.

### Add variables with the Vercel CLI

The Vercel CLI manages variables from your terminal, which fits scripts and repeatable setup. The [`vercel env`](https://vercel.com/docs/cli/env) command group covers adding, updating, listing, removing, and pulling:

```bash
vercel env add [name] [environment] [gitbranch]
vercel env add [name] [environment] [gitbranch] < [file]
vercel env update [name] [environment]
vercel env rm [name] [environment]
vercel env ls [environment] [gitbranch]
vercel env pull [file]
```

Choose a variable's type with `--visibility config` or `--visibility secret` on `vercel env add` or `vercel env update`. When `--visibility` is omitted, the legacy flags still work: `--no-sensitive` maps to Config and `--sensitive` maps to Secret. Passing both `--visibility` and a conflicting legacy flag returns an error. After adding or updating a variable, the CLI output shows its type under Visibility.

### Add variables with the REST API

Automation and infrastructure-as-code setups provision variables programmatically through the REST API. Send a `POST` to the project's environment variables endpoint with a bearer token:

```bash
curl --request POST \
  --url https://api.vercel.com/v10/projects/[idOrName]/env \
  --header "Authorization: Bearer $VERCEL_TOKEN" \
  --header "Content-Type: application/json" \
  --data '[{ "key": "API_KEY", "value": "your_value_here", "type": "sensitive", "visibility": "secret", "target": ["production"] }]'
```

Set `"visibility": "secret"` with `"type": "sensitive"` for write-only Secrets, or `"visibility": "config"` with `"type": "encrypted"` for readable Config values. Add `upsert=true` as a query parameter to update an existing variable instead of returning an error, and `teamId` or `slug` to scope the request to a team.

## Why Vercel environment variable changes need a new deployment

Most environment variable bugs on Vercel come from one assumption, that changing a value takes effect right away the way it does on a long-running server that reads its config at startup. On Vercel, the change applies to the next deployment, and that behavior is deliberate.

Each deployment is an immutable artifact. Its configuration is fixed at build time and doesn't shift afterward, which is what makes instant rollback safe. Rolling back points traffic at an older deployment whose values are exactly what they were when it shipped. Applying a variable change to existing deployments would break that guarantee, so a change requires a redeploy.

`NEXT_PUBLIC_` variables make this concrete. Next.js [inlines them at build time](https://nextjs.org/docs/pages/guides/environment-variables), so a reference like `process.env.NEXT_PUBLIC_ANALYTICS_ID` becomes a hardcoded string in the JavaScript bundle sent to the browser. After the build, the app keeps that bundled value, and no runtime change can update it. Server-only variables differ in one way. Node.js functions read them at runtime through `process.env`, but they still take their values from the deployment that's running.

## How to scope environment variables to each environment

Every variable targets one or more environments, and the target decides which deployments can read it. Scope each variable deliberately so preview builds and production don't read each other's values. The three standard environments map to how a deployment is created:

| Environment | When it applies                                                      |
| ----------- | -------------------------------------------------------------------- |
| Production  | A push to the production branch (usually `main`), or `vercel --prod` |
| Preview     | A push to any non-production branch, or `vercel` without `--prod`    |
| Development | Local development through `vercel dev` or `vercel env pull`          |

Variables can target several environments at once, and you set the targets when you create each one.

### Override preview values for a specific branch

Preview variables can apply to every non-production branch or to one branch. Branch-specific values inherit the general Preview set, so you define only the values you want to override rather than duplicating the whole set for each branch. Managing branch-specific Preview variables from the CLI needs Vercel CLI 21.0.1 or higher.

### Use custom environments for staging or QA

[Custom environments](https://vercel.com/docs/deployments/environments) such as staging or QA are available on Pro and Enterprise plans. Pro allows one custom environment, and Enterprise allows up to 12. Each custom environment can import variables from another environment to start, then diverge as its values change. Pull its values locally with `vercel pull --environment=staging`.

Environment-name branching has one trap. `VERCEL_ENV` returns `preview` for every [custom environment](https://vercel.com/docs/environment-variables/system-environment-variables), so it can't tell staging apart from a standard preview. Read `VERCEL_TARGET_ENV` instead, which returns `production`, `preview`, `development`, or the custom environment's actual name.

### Choose Config or Secret for each variable

Every variable is one of two types, and the type decides who can read the value back after saving. Config values remain readable to members with access, which suits non-sensitive configuration such as public prefixes and values you may need to review later. [Secret values](https://vercel.com/docs/environment-variables/sensitive-environment-variables) are write-only: they stay available to your deployments, but no member can view or retrieve them after saving. Use Secret for passwords, API keys, and tokens. Variables created as Sensitive before this change continue to work as Secrets without migration.

Secrets can target any environment, including Development. This reverses the earlier rule that limited Sensitive environment variables to Production and Preview. Two constraints follow from the write-only design: you can't edit the key of a Secret after saving it, and you can't convert a Secret to Config in place. To rotate a Secret, edit it and provide a new value; to store the same key as Config instead, delete the Secret and create a new Config variable.

One limit affects short credentials. Build-log redaction replaces a Secret value with `[REDACTED]` only when the value is 32 characters or longer, so shorter API keys need manual care to keep them out of logs. Vercel always redacts the `VERCEL_AUTOMATION_BYPASS_SECRET` and `VERCEL_OIDC_TOKEN` system environment variables from build logs, regardless of value length. Each redaction records an [Activity Log](https://vercel.com/docs/activity-log) event with the key name, project, and deployment, but not the value.

The legacy Enforce Sensitive Environment Variables team policy is deprecated, since Config and Secret types let members choose the right classification per variable. Its replacement is Separate Production Secret Values, an optional policy under Settings then Security that a team Owner can enable. When enabled, each Secret must use a different value in Production than in Preview, Development, and custom environments, and the dashboard blocks grouping Production with another target for the same key. Teams that had the legacy policy enabled should review the new setting. After the [April 2026 security incident](https://vercel.com/kb/bulletin/vercel-april-2026-security-incident), Vercel advised customers to rotate any secret values that were not stored as Secrets.

## How to pull Vercel environment variables into local development

Local development reads from the same cloud-defined variables, so there's no separate `.env` file to maintain and drift out of sync. New teammates pull the current values with three commands:

```bash
npm i -g vercel
vercel link
vercel env pull
```

`vercel env pull` writes the Development variables to `.env.local` and adds `.env.local` to `.gitignore` automatically. To pull a different scope, name the environment:

```bash
vercel env pull                                                    # Development to .env.local
vercel env pull --environment=preview                              # Preview variables
vercel env pull --environment=preview --git-branch=feature-branch  # A specific branch
vercel pull --environment=staging                                  # A custom environment
```

Use lowercase environment names in CLI commands (`production`, `preview`, `development`). Note that `vercel pull` and `vercel env pull` are [different commands](https://vercel.com/docs/cli/pull). `vercel env pull` writes a file for a framework dev server like `next dev`, while `vercel pull` caches both variables and project settings for `vercel build` or `vercel dev`.

`vercel dev` downloads Development variables into memory automatically, so it needs no file. When you want to avoid writing secrets to disk at all, `vercel env run` injects them straight into a command:

```bash
vercel env run -e preview --git-branch feature-branch -- npm run dev
```

The `--` separator passes everything after it to your command, so the variables reach the process without ever touching the file system.

## How to troubleshoot environment variables that aren't working

When a variable seems wrong, the cause is usually one of the five documented behaviors below. Work through the one that matches your symptom.

### Your dashboard change hasn't taken effect

Environment variable changes apply to new deployments, so the running deployment keeps its old values. Trigger a new deployment with the Redeploy button (clear Use existing Build Cache), `vercel --force`, or by setting `VERCEL_FORCE_NO_BUILD_CACHE=1` as a project variable.

### Your `NEXT_PUBLIC_` variable is undefined in the browser

Only variables prefixed with `NEXT_PUBLIC_` reach the client bundle, and Next.js inlines them at build time. Dynamic lookups like `process.env[name]` are never inlined, and an empty value reads as `undefined`. Prefix the variable, set it before the build runs, and redeploy. For values that must change without a rebuild, serve them from Global Config or a runtime API instead. ### Your preview deployment reads the wrong values Preview deployments only read variables scoped to Preview. Confirm the Preview target is selected under Settings then Environment Variables. For logic that branches on the environment name, switch from `VERCEL_ENV` to `VERCEL_TARGET_ENV` so custom environments resolve correctly. ### The Turborepo cache serves a build with the wrong values If `env` or `globalEnv` keys are missing from `turbo.json`, Turborepo leaves those values out of its task hash, so a cached build can be reused across environments. Declare `env` per task or `globalEnv` globally, and set `TURBO_FORCE=true` when you need to skip the cache. ### System variables are empty under `vercel dev` Deployment-specific system variables like `VERCEL_GIT_REPO_OWNER` are only set at deployment time, so they stay empty locally. Pull production or preview values with `vercel env pull --environment production`, and set any deployment-time values you need directly in `.env.local`. To confirm a fix, open the deployment in the dashboard and check its Environment. For `NEXT_PUBLIC_` values, inspect the browser bundle or log the value from a client component. For server-only variables, log from an API route and read the function logs. ## Next steps With your variables added and scoped, deploy a project to see them applied. [Start a new Vercel project](https://vercel.com/new) and set its variables in project settings, or [browse the templates](https://vercel.com/templates) for a framework-ready starting point.

## Related resources

- [Environment variables](https://vercel.com/docs/environment-variables)
  
- [Sensitive environment variables](https://vercel.com/docs/environment-variables/sensitive-environment-variables)
  
- [Shared environment variables](https://vercel.com/docs/environment-variables/shared-environment-variables)
  
- [System environment variables](https://vercel.com/docs/environment-variables/system-environment-variables)
  
- [vercel env CLI reference](https://vercel.com/docs/cli/env)
  
- [Environment variables now use Config and Secret types](https://vercel.com/changelog/environment-variables-now-use-config-and-secret-types)
  
- [Vercel April 2026 security incident](https://vercel.com/kb/bulletin/vercel-april-2026-security-incident)
  

## Frequently asked questions

### Do I need to redeploy after adding an environment variable?

Yes. New or changed environment variables take effect on your next deployment, and existing deployments keep the values they were built with. Trigger a deployment with the Redeploy button, `vercel --force`, or a new push. Keeping deployments fixed this way is what makes rollbacks predictable.

### Can I use Secret environment variables in local development?

Yes. Secrets can now target Development, which reverses the earlier rule that limited Sensitive environment variables to Production and Preview. Select Development when you create the Secret with `vercel env add [name] development --visibility secret` or in the dashboard. Because Secret values are write-only after saving, `vercel env pull` writes a placeholder rather than the real value \[VERIFY: confirm current `vercel env pull` output for Development-scoped Secrets\], so keep locally-managed secret values in your own `.env.local` file. ### What is the maximum number of environment variables per project? Each environment in a project can hold up to [1,000 environment variables](https://vercel.com/docs/limits). All variables in a deployment share a 64 KB total size limit for Node.js, Python, Ruby, Go, Java, and .NET runtimes, which is also the largest a single variable can be. For the Edge runtime, each variable is limited to 5 KB.

### How do I share one variable across multiple projects?

Create a [shared environment variable](https://vercel.com/docs/environment-variables/shared-environment-variables) in Team Settings and link it to each project, available on Pro and Enterprise plans. Shared variables support the same Config and Secret types as project variables. Updating the shared value updates every linked project. Project-level variables with the same key and environment override the shared value, and shared variables don't support branch-specific scoping.

### What happened to the `vercel secrets` command?

Vercel converted legacy secrets to sensitive environment variables on May 1, 2024, for Production and Preview environments, and Development secrets were not migrated. Sensitive environment variables were later replaced by the Secret type, and existing Sensitive variables continue to work as Secrets. Use `vercel env add` with `--visibility secret`, or set `"type": "sensitive"` and `"visibility": "secret"` in the REST API to create write-only values.