Environment variables keep secrets out of your code. This guide covers .env file conventions, loading variables with dotenv, separating dev and prod configs, and what never to commit to git.
In this guide
Create a .env file in your project root: DATABASE_URL=postgresql://user:pass@localhost/mydb — STRIPE_SECRET_KEY=sk_test_xxx — REDIS_URL=redis://localhost:6379 — NODE_ENV=development. Add .env to .gitignore immediately — before the first commit. Create .env.example with the same keys but empty values and commit that instead. New team members copy .env.example to .env and fill in their own values.
Install: npm install dotenv. Add at the very start of your entry file: import "dotenv/config" (ESM) or require("dotenv").config() (CommonJS). Variables are now available as process.env.DATABASE_URL. In Next.js, dotenv is built in — any variable in .env.local is automatically available server-side. Variables prefixed with NEXT_PUBLIC_ are also available client-side. Never prefix secret keys with NEXT_PUBLIC_.
Use multiple env files for different environments: .env (shared defaults, committed), .env.local (local overrides, gitignored), .env.test (test-specific values, can be committed if no secrets), .env.production (production overrides — never commit). In production, set environment variables through your hosting platform (AWS Parameter Store, Heroku Config Vars, Vercel Environment Variables, .env on server via deployment script) — not via files.
Fail fast if required variables are missing — better to crash on startup than to fail silently at runtime. Use zod for validation: import { z } from "zod"; const env = z.object({ DATABASE_URL: z.string().url(), STRIPE_SECRET_KEY: z.string().startsWith("sk_"), PORT: z.coerce.number().default(3000) }).parse(process.env). This throws a clear error listing all missing variables before your app starts accepting requests.
Run git log --all --full-history -- .env to check if any .env file was ever committed, even if later deleted (git history preserves it). If secrets were committed: rotate them immediately (generate new API keys, change passwords) — then use git-filter-repo or BFG Repo Cleaner to rewrite history and remove the file. Treat any committed secret as compromised regardless of whether the repo is private.
Need Help?
Our engineering team handles implementations like this every week. Get a free scoping call — we will tell you exactly what it takes and what it costs.
Book a free callCompetitive Intelligence
Efficiency Modeling
© 2026 NexWorldTech — Built for Global Dominance.