Next.js Curriculum
MediumProduction Operations100% Free25 min read

Managing Environment Variables & Build-Time Inlining

The 30-Second Interview Answer

Next.js differentiates between private server-side environment variables and public client-side variables prefixed with NEXT_PUBLIC_. Private variables are evaluated at runtime on the server, while NEXT_PUBLIC_ variables are statically inlined (hardcoded) into client JavaScript bundles during next build. Modifying NEXT_PUBLIC_ variables requires a complete rebuild.

Learning Objectives

Differentiate server-only variables from NEXT_PUBLIC_ client-inlined variables.

Avoid accidental production data leaks caused by variable prefix misconfigurations.

Validate environment variables at build/startup using @t3-oss/env-nextjs and Zod.

Handle runtime dynamic environment variables in Docker and Kubernetes.

Prerequisites & Background Knowledge
Node.js process.envWebpack/Turbopack string replacementTwelve-Factor App config

Why Interviewers Care

Frequent cause of broken deployments and security leaks in production environments.

The Challenge

Explain how Next.js treats private environment variables versus NEXT_PUBLIC_ variables. Implement type-safe environment variable validation using Zod that halts invalid builds immediately.

Code Architecture & Implementation

1// lib/env.ts
2import { z } from 'zod';
3
4// Schema validating environment variables at build and boot time
5const EnvSchema = z.object({
6 // Server-only secrets: MUST NOT start with NEXT_PUBLIC_
7 DATABASE_URL: z.string().url('Invalid database connection URL'),
8 JWT_SECRET: z.string().min(32, 'JWT secret must be at least 32 characters'),
9 NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
10
11 // Public client variables: MUST start with NEXT_PUBLIC_
12 NEXT_PUBLIC_SITE_URL: z.string().url(),
13 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().startsWith('pk_'),
14});
15
16// Parse process.env; throws descriptive error if variables are missing!
17const parsedEnv = EnvSchema.safeParse(process.env);
18
19if (!parsedEnv.success) {
20 console.error('❌ CRITICAL: Invalid environment variables:');
21 console.error(JSON.stringify(parsedEnv.error.format(), null, 2));
22 process.exit(1); // Fail the build immediately!
23}
24
25export const env = parsedEnv.data;

Architectural Explanation

Because the browser has no operating system environment, client-accessible variables must be bundled into JavaScript files. Next.js searches for process.env.NEXT_PUBLIC_* references and replaces them with their actual string values during compilation. If you deploy a Docker image to production with NEXT_PUBLIC_API_URL set at container runtime, it will have NO effect because the value was already hardcoded during npm run build. Server-side variables without NEXT_PUBLIC_ are read dynamically from the host environment on every request.

Common Mistakes & Anti-Patterns

Prefixing sensitive API keys with `NEXT_PUBLIC_` (e.g. `NEXT_PUBLIC_STRIPE_SECRET_KEY`), publicly exposing secrets in the browser console.

Expecting `NEXT_PUBLIC_` variables to change dynamically at Docker container startup without rebuilding.

Not validating environment variables in CI/CD, allowing deployments with missing configuration to crash at runtime.

Interview Follow-Up Traps

The interviewer asks: "What happens if a Client Component attempts to read process.env.DATABASE_URL?" Next.js replaces it with `undefined` in client bundles to protect the secret, but a TypeScript warning or runtime bug will occur.

Frequently Asked Questions

Which .env file takes highest priority in Next.js?

`.env.local` overrides all other files (`.env.production`, `.env.development`, `.env`).

Pass runtime config via an un-cached `/api/config` endpoint or window.__RUNTIME_CONFIG__ script.

Never! `.env.local` should be in `.gitignore` to keep developer credentials secure.