Use .env files with dotenv for development, environment variables for production, and validate config at startup with libraries like Zod or envalid.
Configuration management keeps secrets safe and makes deployments flexible.
dotenv loads .env files in development: require('dotenv').config() at app startup reads KEY=value pairs into process.env. Different files per environment (.env.local, .env.test) keep configs separate.
Never commit secrets. Add .env to .gitignore. Use .env.example (committed) to document required variables without values. Developers copy it to .env and add their secrets.
In production, set real environment variables through your hosting platform (Vercel, Railway, AWS). These override any .env files and keep secrets out of your codebase.
Validate configuration at startup. Use Zod or envalid to define expected variables, their types, and defaults. If required config is missing, fail fast with a clear error rather than discovering it later during runtime.
Create a typed config object: const config = { database: { url: env.DATABASE_URL }, api: { port: env.PORT ?? 3000 } }. Access config.database.url rather than process.env.DATABASE_URL throughout your code. This centralizes validation and provides autocomplete.
For sensitive configs (API keys, database passwords), consider secret managers in production: AWS Secrets Manager, HashiCorp Vault. They provide rotation, auditing, and secure access patterns beyond environment variables.
Use .env files with dotenv for development, environment variables for production, and validate config at startup with libraries like Zod or envalid.
Join our network of elite AI-native engineers.