Minimum requirements to run Next.js
To run Next.js, your platform needs a Node.js server. A single `next start` process handles every Next.js feature correctly including Server Components, ISR, PPR, Cache Components, Server Actions, Proxy, and `after()`. The `sharp` package is the only additional dependency, required for Image Optimization.
Feature support matrix: Server Components streaming requirement
Server Components require streaming support. Streaming is necessary for progressive content delivery; without it, responses are buffered and sent as a whole, losing the streaming performance benefit. Shared cache is not required. Edge stitching is not required.
Feature support matrix: ISR time-based caching
ISR with time-based expiration does not require streaming. Shared cache is recommended but not required; ISR works per-instance without shared cache. Edge stitching is not required. Without shared cache, each instance maintains its own cache independently.
Feature support matrix: ISR on-demand revalidation
ISR with on-demand revalidation does not require streaming. Shared cache is recommended. Tag propagation requires shared cache for multi-instance deployments. Edge stitching is not required.
Feature support matrix: Partial Prerendering
Partial Prerendering requires streaming support. Shared cache is recommended. Edge stitching is optional for performance optimization. See PPR Platform Guide for detailed requirements.
Feature support matrix: Cache Components use cache directive
Cache Components (`use cache`) require streaming support. Shared cache is recommended to enable cross-instance consistency. Edge stitching is not required. Without shared cache, each instance maintains its own cache independently.
Feature support matrix: Proxy and Middleware
Proxy and Middleware require no streaming support. Shared cache is not required. Edge stitching is not required. These features run at edge or origin.
Feature support matrix: Server Actions
Server Actions require streaming support for POST requests with streaming response. Shared cache is not required. Edge stitching is not required.
Feature support matrix: after() function
The `after()` function requires no streaming support. Shared cache is not required. Edge stitching is not required. It requires graceful shutdown support.
Streaming Required definition in Next.js deployment
Streaming Required means the platform must support chunked transfer encoding or HTTP/2 streaming and must not buffer the response before sending it to the client.
Shared Cache Recommended meaning in deployment
Shared Cache Recommended means multiple server instances benefit from shared cache backends to coordinate. For ISR and server response caching, use `cacheHandler`. For `use cache` entries, use `cacheHandlers`. Without shared cache, each instance maintains its own cache independently, but features still work correctly on each instance; revalidation events don't propagate across instances.
CDN infrastructure compatibility table
CDN providers offer different infrastructure primitives for Next.js deployment: Cloudflare provides Workers (edge compute), KV (key-value/tags), R2 (blob storage), and worker-based PPR resuming. Akamai provides EdgeWorkers, EdgeKV, Object Storage, and worker-based PPR resuming. Amazon CloudFront provides Lambda@Edge, KeyValueStore, S3, and Lambda-based PPR resuming. Fastly provides Compute, KV Store, Object Storage, and WASM-based PPR resuming. Azure provides Functions, Managed Redis, Blob Storage, and server-based PPR resuming. Google Cloud provides Cloud Run, Various KV, Cloud Storage, and server-based PPR resuming.
CDN infrastructure primitives are building blocks not finished integrations
The CDN infrastructure compatibility table lists available building blocks, not finished integrations. Most community adapters deploy Next.js as a Docker container or Node.js server without leveraging CDN-specific primitives like edge KV or PPR resuming.
Deployment Adapter API overview
Next.js provides a Deployment Adapter API that lets platforms customize how Next.js applications are built and deployed for their infrastructure. Adapters run at build time and produce platform-specific output from the standard Next.js build. Anyone can build an adapter using the public API with no special access required.
Caching interfaces for platform integration
The adapter API plus Next.js caching interfaces form the complete platform integration surface. `cacheHandler` (singular) covers server cache paths like ISR, route handlers, patched `fetch`/`unstable_cache`, and image optimization. `cacheHandlers` (plural) configures `use cache` directive backends.
Verified adapter definition and requirements
A verified adapter is one that meets two requirements: (1) Open source - the adapter source code is publicly available so the community and Next.js team can inspect, contribute to, and verify it. (2) Runs the compatibility test suite - the platform provides a way to run the full Next.js compatibility test suite against their adapter. Verified adapters are hosted under the Next.js GitHub organization and listed as supported deployment targets.
Verified adapter commitments from Next.js team
For verified adapters and platforms working toward verified status, the Next.js team commits to: (1) Coordinated testing - before major releases, working with platform teams to run the compatibility test suite and surface issues early. (2) Early access - adapter authors receive early access to API changes during RFCs and release candidates. (3) Direct support - when the adapter contract needs updating, the team works directly with adapter teams.
Closed-source adapters and verification status
Platforms can build closed-source adapters on the same public API and test suite. However, closed-source adapters will not be listed as verified, since the Next.js team cannot verify what it cannot inspect.
Component-level static/dynamic boundary tradeoff in Next.js deployment
Next.js places the static/dynamic boundary at the component level rather than the route level. Finer-grained boundaries provide more flexibility for developers at the cost of broader requirements for hosting platforms. The infrastructure requirements exist because of what the rendering model delivers.
deploymentId mitigates cross-deployment skew
During rolling deployments, a client built with deploy A may receive responses from a server running deploy B. The deploymentId configuration mitigates this: when the client detects a different deployment ID from the server, it triggers a hard navigation to fetch consistent content.
Loading environment variables from .env files
Next.js has built-in support for loading environment variables from `.env*` files into `process.env`. You create a `.env` file at the root of your project with key-value pairs like `DB_HOST=localhost`, and Next.js automatically loads them. These variables become available in `process.env` and can be used in Route Handlers, Server Components, and other server-side code.
NEXT_PUBLIC_ prefix for browser-accessible environment variables
Environment variables prefixed with `NEXT_PUBLIC_` are inlined into the JavaScript bundle at build time, making them accessible in the browser. Non-prefixed variables are only available in the Node.js environment on the server. For example, `NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk` will have its value inlined into all JavaScript sent to the client, while a variable without this prefix will not be accessible to browser code.
.env files should not be committed to version control
The default `create-next-app` template adds all `.env` files to `.gitignore`. You should never commit `.env` files to your repository as they typically contain sensitive information like database credentials and secrets.
Multiline environment variables in .env files
Next.js supports multiline variables in `.env*` files. You can write multiline content either with literal line breaks or by using `\n` escape sequences inside double quotes. For example, a private key can be stored as: `PRIVATE_KEY="---••••••--\nKh9NV...\n-----END DSA PRIVATE KEY-----\n"`
.env file location with /src directory
If you are using a `/src` folder in your Next.js project, `.env*` files should remain in the root of the project, not in the `/src` folder. Next.js will only load `.env*` files from the parent folder, not from `/src`.
Variable referencing in .env files
Next.js automatically expands variables that use `$` to reference other variables in `.env*` files. For example, if you have `TWITTER_USER=nextjs` and `TWITTER_URL=https://x.com/$TWITTER_USER`, the second variable will be expanded to `https://x.com/nextjs`. If you need a literal `$` in the value, escape it with a backslash: `\$`.
NEXT_PUBLIC_ variables are frozen at build time
After your app is built, it no longer responds to changes in `NEXT_PUBLIC_` environment variables. These values are frozen with the value evaluated at build time. If you promote a Docker image built in one environment to another environment with different values, the `NEXT_PUBLIC_` variables will retain the values from the build environment. To use runtime environment values on the client, you must set up your own API to provide them.
Dynamic lookups of environment variables are not inlined
Dynamic lookups using variable names or destructuring patterns will not be inlined for `NEXT_PUBLIC_` variables. For example, `process.env[varName]` or destructuring like `const env = process.env; env.NEXT_PUBLIC_ANALYTICS_ID` will not be inlined. Only direct static references like `process.env.NEXT_PUBLIC_ANALYTICS_ID` are inlined.
Runtime environment variables in dynamic rendering
You can safely read environment variables on the server during dynamic rendering by using the `connection()` function from `next/server`. This opts into dynamic rendering, meaning the environment variable is evaluated at runtime rather than at build time. For example: `import { connection } from 'next/server'` followed by `await connection()` allows you to read `process.env.MY_VALUE` at request time.
Loading environment variables outside Next.js runtime with @next/env
The `@next/env` package provides the `loadEnvConfig` function to load environment variables from `.env*` files outside of the Next.js runtime. This is useful for root config files of ORMs or test runners. You install it with `npm install @next/env`, then use: `import { loadEnvConfig } from '@next/env'; loadEnvConfig(process.cwd());` to load the variables.
Test environment variables with .env.test
Next.js supports a third environment called `test` in addition to `development` and `production`. Create a `.env.test` file to set environment variables for testing. When `NODE_ENV` is set to `test`, Next.js loads variables from `.env.test` but does not load from `.env.development` or `.env.production`. Unlike development and production, `.env.local` is not loaded in the test environment to ensure tests produce consistent results for everyone.
.env.test.local should not be committed but .env.test should be
The `.env.test` file should be included in your repository, but `.env.test.local` should not. This follows the pattern that `.env*.local` files are intended to be ignored via `.gitignore`, while the default `.env.test` file should be shared across all developers.
Environment variable load order
Next.js looks up environment variables in the following order, stopping once the variable is found: 1) `process.env`, 2) `.env.$(NODE_ENV).local`, 3) `.env.local` (not checked when NODE_ENV is test), 4) `.env.$(NODE_ENV)`, 5) `.env`. For example, if NODE_ENV is `development`, a variable defined in `.env.development.local` takes precedence over the same variable in `.env`.
Default NODE_ENV values in Next.js
If the environment variable NODE_ENV is unassigned, Next.js automatically assigns `development` when running the `next dev` command, or `production` for all other commands. The allowed values for NODE_ENV are `production`, `development`, and `test`.
Example: using environment variables in Route Handlers
In a Route Handler at `app/api/route.js`, you can access environment variables loaded from `.env` files: `export async function GET() { const db = await myDB.connect({ host: process.env.DB_HOST, username: process.env.DB_USER, password: process.env.DB_PASS, }) }`
Example: using NEXT_PUBLIC_ variables in browser code
NEXT_PUBLIC_ variables are inlined at build time into browser JavaScript. Example in `pages/index.js`: `import setupAnalyticsService from '../lib/my-analytics-service'; setupAnalyticsService(process.env.NEXT_PUBLIC_ANALYTICS_ID)`. This will be transformed at build time to `setupAnalyticsService('abcdefghijk')` if the variable value is `abcdefghijk`.
Example: loading environment variables in test setup with @next/env
In a Jest global setup file, you can load environment variables the same way Next.js does: `import { loadEnvConfig } from '@next/env'; export default async () => { const projectDir = process.cwd(); loadEnvConfig(projectDir); }`
Example: using loadEnvConfig in ORM configuration
After importing and calling `loadEnvConfig` in your configuration file, you can use environment variables in your ORM config: `import './envConfig.ts'; export default defineConfig({ dbCredentials: { connectionString: process.env.DATABASE_URL! } })`
Example: reading runtime environment variables during dynamic rendering
To read environment variables at runtime in dynamic rendering: `import { connection } from 'next/server'; export default async function Component() { await connection(); const value = process.env.MY_VALUE; }`