HeoLab
ToolsBlogAboutContact
HeoLab

Free developer tools with AI enhancement. Built for developers who ship.

Tools

  • JSON Formatter
  • JWT Decoder
  • Base64 Encoder
  • Timestamp Converter
  • Regex Tester
  • All Tools →

Resources

  • Blog
  • What is JSON?
  • JWT Deep Dive
  • Base64 Explained

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 HeoLab. All rights reserved.

Tools work in your browser. Zero data retention.

HomeBlogManaging Environment Variables: Best Practices for Every Environment
Table of Contents▾
  • The Twelve-Factor App Rule
  • .env File Format
  • Comments start with #
  • Quoted values (required if value contains spaces or # chars)
  • Multiline values (some loaders support this)
  • Empty value
  • Inline comments (NOT supported by all loaders — avoid!)
  • File Conventions by Environment
  • Validating Env Variables at Startup
  • Secrets Management in Production
  • Example: pull secrets from AWS Secrets Manager at startup
  • Common Mistakes
  • Generating .env.example
  • Database
  • Authentication
  • External APIs (optional — AI features disabled if not set)
  • App
guides#environment-variables#dotenv#secrets

Managing Environment Variables: Best Practices for Every Environment

How to properly manage .env files across development, staging, and production — secrets management, validation, and common pitfalls to avoid.

Trong Ngo
February 23, 2026
3 min read

Environment variables are how modern applications handle configuration — keeping secrets out of source code and making apps portable across environments. But most developers use them incorrectly. Here's the complete guide.

The Twelve-Factor App Rule

The Twelve-Factor methodology says: store config in environment, not in code. Everything that varies between deployments (dev, staging, production) belongs in environment variables:

  • Database credentials
  • API keys and secrets
  • Service URLs and ports
  • Feature flags
  • OAuth client IDs

.env File Format

# Comments start with #
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb

# Quoted values (required if value contains spaces or # chars)
APP_NAME="My Cool App"
DESCRIPTION='Has a # hash'

# Multiline values (some loaders support this)
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----"

# Empty value
OPTIONAL_FEATURE=

# Inline comments (NOT supported by all loaders — avoid!)
PORT=3000 # This comment may break some loaders

File Conventions by Environment

FilePurposeIn git?
.envDefaults for all environmentsSometimes
.env.localLocal overrides, machine-specificNever
.env.developmentDevelopment-only valuesSometimes
.env.productionProduction defaults (no secrets!)Sometimes
.env.exampleTemplate with fake values, for docsAlways
.env.testTest environment valuesSometimes

Rule: Never commit .env.local or any file with real credentials. Always commit .env.example.

Validating Env Variables at Startup

Crashing at startup with a clear error is better than mysterious runtime failures. Validate all required env vars when your app boots:

// env.ts — validate with Zod
import { z } from 'zod';

const envSchema = z.object({
  DATABASE_URL: z.string().url(),
  JWT_SECRET: z.string().min(32),
  PORT: z.coerce.number().default(3000),
  NODE_ENV: z.enum(['development', 'staging', 'production']),
  OPENAI_API_KEY: z.string().optional(),
});

export const env = envSchema.parse(process.env);
// Throws at startup if any required var is missing or invalid

Secrets Management in Production

Never store real secrets in .env files in production. Use proper secrets management:

ProviderTool
AWSAWS Secrets Manager, SSM Parameter Store
GCPSecret Manager
AzureAzure Key Vault
VercelVercel Environment Variables
Self-hostedHashiCorp Vault, Doppler
# Example: pull secrets from AWS Secrets Manager at startup
aws secretsmanager get-secret-value --secret-id prod/myapp/env

Common Mistakes

1. Committing .env to git — add .env* to .gitignore (but allow .env.example).

2. Hardcoding defaults in code — process.env.PORT || 3000 is fine for non-sensitive values, but document required vars in .env.example.

3. Using REACT_APP_ or NEXT_PUBLIC_ for secrets — these prefixes expose values to the browser bundle. Never use them for API keys or secrets.

4. Not rotating compromised secrets — if a secret is accidentally committed to git, it's compromised forever (git history). Rotate it immediately.

5. Using the same secret across environments — development and production should have different keys, secrets, and credentials.

Generating .env.example

Your .env.example should list every variable your app needs, with placeholder values and comments:

# Database
DATABASE_URL=postgresql://user:password@localhost:5432/dbname

# Authentication
JWT_SECRET=change-this-to-a-random-32-char-string
SESSION_SECRET=change-this-too

# External APIs (optional — AI features disabled if not set)
OPENAI_API_KEY=sk-...

# App
NEXT_PUBLIC_SITE_URL=http://localhost:3000

Use the .env Parser tool to validate your .env files, find duplicate keys, and export them as JSON for debugging.

Try These Tools

.env Parser & Formatter

Paste .env content to parse, validate, sort, and export as JSON or a table.

Related Articles

YAML vs JSON: When to Use Each and How to Convert Between Them

3 min read

Understanding OAuth 2.0 and OpenID Connect: A Developer's Guide

3 min read

Docker Commands Cheatsheet for Developers

4 min read

Back to Blog

Table of Contents

  • The Twelve-Factor App Rule
  • .env File Format
  • Comments start with #
  • Quoted values (required if value contains spaces or # chars)
  • Multiline values (some loaders support this)
  • Empty value
  • Inline comments (NOT supported by all loaders — avoid!)
  • File Conventions by Environment
  • Validating Env Variables at Startup
  • Secrets Management in Production
  • Example: pull secrets from AWS Secrets Manager at startup
  • Common Mistakes
  • Generating .env.example
  • Database
  • Authentication
  • External APIs (optional — AI features disabled if not set)
  • App

Related Articles

YAML vs JSON: When to Use Each and How to Convert Between Them

3 min read

Understanding OAuth 2.0 and OpenID Connect: A Developer's Guide

3 min read

Docker Commands Cheatsheet for Developers

4 min read