# How to Manage Environment Variables for Different Deployment Environments in Next.js

> Effectively manage Next.js environment variables for deployments beyond .env.local. Use Next.js @next/env to create mode-specific .env files for seamless management across development, staging, and production.

- Repository: [Vercel/next.js](https://github.com/vercel/next.js)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Use Next.js's built-in @next/env loader to create mode-specific .env files (such as .env.production, .env.staging, and .env.development) that automatically load based on the current build phase without requiring custom configuration or third-party libraries.**

Managing environment variables across multiple deployment environments—including development, staging, and production—requires a robust strategy beyond the standard .env.local file. Next.js provides a powerful, built-in solution through the **@next/env** package, which automatically loads environment files based on the current build mode. This approach eliminates the need for custom loading scripts while maintaining clean separation between environment-specific configurations.

## Understanding Next.js Environment File Loading Order

The core mechanism for environment variable management resides in the **@next/env** package. When the Next.js server initializes or the build process starts, it invokes `loadEnvConfig(dir, dev, log)` from [`packages/next-env/index.ts`](https://github.com/vercel/next.js/blob/main/packages/next-env/index.ts). This function is called during server startup in [`packages/next/src/server/config.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/server/config.ts) (around line 1580) and determines which files to load based on the current phase.

### The Four-Layer Precedence System

The `loadEnvConfig` function constructs an ordered list of files, loading them sequentially with later files overriding earlier ones. According to the implementation in [`packages/next-env/index.ts`](https://github.com/vercel/next.js/blob/main/packages/next-env/index.ts) (lines 38-46), the loading order is:

1. **`.env.{mode}.local`** — Environment-specific local overrides (e.g., `.env.production.local`). Loaded first but overridden by later files in the chain.
2. **`.env.local`** — General local overrides. **Skipped entirely** when mode is **test** to ensure test determinism.
3. **`.env.{mode}`** — Environment-specific defaults (e.g., `.env.staging`, `.env.development`).
4. **`.env`** — Global defaults loaded last, providing base values for all environments.

The **mode** is derived from the phase Next.js runs in: `development` (during `next dev`), `production` (during `next build` with `NODE_ENV=production`), or `test` (during testing). You can also specify custom modes by setting the `NODE_ENV` environment variable.

### How Build Modes Determine File Selection

When you execute `next build`, Next.js checks the current phase and passes this information to `loadEnvConfig`. In [`packages/next/src/server/config.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/server/config.ts), the configuration loader determines whether the current context is development, production, or a custom mode, then loads the corresponding environment files.

For example, running `NODE_ENV=staging next build` triggers the loading of `.env.staging.local`, `.env.local`, `.env.staging`, and `.env` in that order. This allows you to maintain separate configurations for preview deployments, staging servers, and production environments without modifying your application code.

## Setting Up Environment Files for Multiple Deployment Targets

To effectively manage environment variables across different deployment environments, create mode-specific files in your project root alongside the standard `.env.local` file.

### Standard Environment Configuration

For the three primary environments supported by Next.js, create the following files:

- **`.env.development`** — Default variables for local development (e.g., API endpoints pointing to localhost).
- **`.env.production`** — Default variables for production builds (e.g., production API endpoints).
- **`.env.local`** — Local overrides that should never be committed (contains secrets, personal API keys).

When running `next dev`, Next.js automatically loads `.env.development.local`, `.env.local`, `.env.development`, and `.env`.

### Creating Custom Environment Modes (Staging)

For environments like **staging** or **qa** that fall between development and production, leverage custom modes by setting `NODE_ENV`:

```json
// package.json
{
  "scripts": {
    "build:staging": "NODE_ENV=staging next build",
    "build:production": "next build"
  }
}

```

Create the corresponding files:

- **`.env.staging`** — Staging-specific defaults (e.g., staging API URL).
- **`.env.staging.local`** — Local staging overrides.

When you run `npm run build:staging`, Next.js loads the staging environment files in the standard precedence order, allowing you to deploy to preview environments with distinct configurations from production.

## Accessing Environment Variables in Your Application

Once the environment files are loaded via `loadEnvConfig`, variables are available via `process.env` throughout your application.

### Server-Side Access

In API routes, server components (App Router), or `getServerSideProps`, access variables directly:

```typescript
// app/api/config/route.ts
export async function GET() {
  const apiKey = process.env.API_KEY;
  const environment = process.env.NODE_ENV;
  
  return Response.json({ environment, apiKey });
}

```

### Client-Side Access

To expose variables to the browser, prefix them with `NEXT_PUBLIC_`:

```bash

# .env.production

NEXT_PUBLIC_API_URL=https://api.production.com
API_SECRET_KEY=server-only-secret

```

```typescript
// components/ApiClient.tsx
export default function ApiClient() {
  // Available in browser
  const apiUrl = process.env.NEXT_PUBLIC_API_URL;
  
  return <div>Connecting to {apiUrl}</div>;
}

```

## Integrating with CI/CD and Vercel

When deploying through CI/CD pipelines or platforms like Vercel, environment variable management extends beyond local files.

### Vercel Deployment Considerations

Vercel automatically injects environment variables defined in the project dashboard during the build process. According to the Next.js source implementation in [`packages/next-env/index.ts`](https://github.com/vercel/next.js/blob/main/packages/next-env/index.ts), these platform-injected variables are merged into `process.env` **after** the `.env` files are loaded via `loadEnvConfig`. This means:

- Vercel dashboard variables override values in `.env.production`
- You can combine static files with Vercel's UI-defined secrets
- Preview deployments automatically use the appropriate environment based on your Git branch settings

### CI/CD Pipeline Configuration

In GitHub Actions, GitLab CI, or similar platforms, set environment variables before running the build:

```yaml

# .github/workflows/deploy-staging.yml

jobs:
  build:
    runs-on: ubuntu-latest
    environment: staging
    env:
      NODE_ENV: staging
      API_KEY: ${{ secrets.STAGING_API_KEY }}
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build

```

The `NODE_ENV=staging` setting ensures Next.js loads `.env.staging` files, while the `API_KEY` environment variable takes precedence over file-defined values.

## Summary

- **Use mode-specific files**: Create `.env.development`, `.env.staging`, and `.env.production` to separate configurations by deployment target.
- **Leverage @next/env**: The framework automatically loads files via `loadEnvConfig` in [`packages/next-env/index.ts`](https://github.com/vercel/next.js/blob/main/packages/next-env/index.ts), following a strict precedence order.
- **Respect the loading order**: Files load as `.env.{mode}.local` → `.env.local` → `.env.{mode}` → `.env`, with later values overriding earlier ones.
- **Combine with platform variables**: Vercel and CI/CD injected variables merge after file loading, allowing hybrid approaches for secrets management.
- **Use custom modes**: Set `NODE_ENV` to custom values like `staging` to trigger loading of `.env.staging` files during builds.

## Frequently Asked Questions

### How do I add a staging environment to Next.js?

Create a `.env.staging` file in your project root with staging-specific variables, then run your build with `NODE_ENV=staging next build`. Next.js will automatically load `.env.staging.local`, `.env.local`, `.env.staging`, and `.env` in that order. You can add a convenience script to your [`package.json`](https://github.com/vercel/next.js/blob/main/package.json) such as `"build:staging": "NODE_ENV=staging next build"` to simplify the process.

### Can I use multiple .env files in production?

Yes, Next.js supports multiple environment files in production builds. The framework loads `.env.production.local`, `.env.local`, `.env.production`, and `.env` when running `next build` with `NODE_ENV=production`. However, `.env.production.local` and `.env.local` should typically be excluded from version control via `.gitignore`, so production deployments often rely on `.env.production` committed to the repository combined with platform-injected variables from Vercel or CI/CD systems.

### What takes precedence: Vercel environment variables or .env files?

Vercel environment variables take precedence over values defined in `.env` files. According to the Next.js source code in [`packages/next-env/index.ts`](https://github.com/vercel/next.js/blob/main/packages/next-env/index.ts), the `loadEnvConfig` function processes local files first, then Vercel injects its variables into `process.env` after the build starts. This means a variable defined in the Vercel dashboard will override the same variable defined in `.env.production`, allowing you to keep sensitive production secrets out of your repository while maintaining default configurations in files.

### How does Next.js handle environment variables during next build?

During `next build`, Next.js calls `loadEnvConfig` from `@next/env` (implemented in [`packages/next-env/index.ts`](https://github.com/vercel/next.js/blob/main/packages/next-env/index.ts)) to load environment files based on the current mode. The function constructs a list of files in specific precedence order: `.env.{mode}.local`, `.env.local`, `.env.{mode}`, and `.env`. It then parses each file and merges the variables into `process.env`, with later files overriding earlier ones. This happens before the build process begins, ensuring all environment variables are available during compilation, static generation, and server initialization.