env.dev

The .env File: A Complete Guide to Environment Variables

Everything about .env files: syntax rules, parser quirks, language examples (Node, Python, Go, Docker), best practices, and the gotchas that bite.

Last updated:

What is a .env file? It's a plain-text configuration file that stores environment variables as KEY=value pairs, one per line, loaded into your process at startup so secrets and config never get hardcoded into source. The pattern started as a Ruby gem from Brandon Keepers in 2012, crossed to Node.js the next year via Scott Motte's motdotla/dotenv, and now ships with parsers for every major language. As of Node.js 20.6 (August 2023), you don't even need a library — node --env-file=.env app.js reads the file natively. Bun auto-loads .env with no flag at all; Deno requires both --env-file and --allow-env for sandbox reasons (see the Bun vs Deno vs Node comparison).

How do .env files work?

At process startup, a dotenv parser reads the file line by line and injects each KEY=value pair into the OS environment. In Node.js the values appear on process.env, in Python on os.environ, and so on. The file itself sits next to your code during local development, never gets deployed, and belongs in .gitignore — committing one is the fastest way to leak production credentials.

The pattern descends from the 12-Factor App methodology, published by Heroku co-founder Adam Wiggins in 2011, which says configuration should be strictly separated from code and stored in the environment. There is no formal RFC for the format itself, which is why parser quirks bite in production: a stray space in KEY = value silently breaks the Node.js parser but works fine when sourced from a shell.

What is the .env file syntax?

The .env format is intentionally simple, but there are a few rules worth knowing:

Basic assignment

Keys are uppercase by convention. There must be no spaces around the = sign.

ini
DATABASE_HOST=localhost
PORT=3000

Quoted values

Double quotes allow spaces and special characters. Single quotes treat the value as a literal string with no interpolation.

ini
GREETING="Hello, World!"
REGEX='\d+\.\d+'

Comments and empty values

Lines starting with # are comments. KEY= sets an empty string, as does KEY="".

ini
# Database config
DB_PASSWORD=
DB_NAME=""

Multiline and variable expansion

Some parsers support multiline values in double quotes and variable expansion with ${} syntax.

ini
PRIVATE_KEY="-----BEGIN RSA KEY-----
MIIBogIBAAJBALRi...
-----END RSA KEY-----"

BASE_URL=https://api.example.com
FULL_URL=${BASE_URL}/v1/users

For an exhaustive parser-by-parser reference — every quoting rule, escape behaviour, and interpolation quirk across Node.js, Python, Ruby, Go, and Docker — see the .env file syntax reference. Here is a complete example:

ini
# App
NODE_ENV=development
PORT=3000

# Database
DATABASE_URL="postgres://user:pass@localhost:5432/mydb"
DATABASE_POOL_SIZE=10

# External APIs
STRIPE_SECRET_KEY=sk_test_abc123
SENDGRID_API_KEY="SG.xxxx"

# Feature flags
ENABLE_CACHE=true

How do I load .env files in different languages?

Every major language has a dotenv library. Here is how to get started in the most popular ones:

LanguageSetupAccess
Node.jsimport 'dotenv/config'process.env.KEY
Pythonfrom dotenv import load_dotenvos.getenv('KEY')
Gogodotenv.Load()os.Getenv("KEY")
Dockerenv_file: .env in composeInjected into container environment

What are .env file best practices?

  1. Never commit .env to git. Add it to your .gitignore immediately. Leaked secrets are the number one cause of security incidents.
  2. Provide a .env.example. Commit a template file with dummy values so new team members know which variables are required.
  3. Validate at startup. Fail fast if a required variable is missing or malformed. Libraries like envalid (Node.js) or pydantic-settings (Python) make this easy.
  4. Use typed configuration objects. Instead of sprinkling process.env.X throughout your codebase, parse variables into a typed config object at the entry point.
  5. Separate secrets from config. Non-sensitive values like PORT or LOG_LEVEL can live in .env, but production secrets belong in a secrets manager (Vault, AWS SSM, etc.). For local team workflows, a dev container can mount secrets from the host instead of committing a checked-in .env.
  6. Use per-environment files. Many frameworks support .env.development, .env.production, and .env.test to keep environments cleanly separated.

What are common .env file pitfalls?

  • Whitespace around =KEY = value will break most parsers. Always use KEY=value with no spaces.
  • Unquoted values with #URL=https://x.com#anchor will be truncated at the # because it is treated as an inline comment. Wrap the value in quotes instead.
  • .env is NOT for production secrets — In production, use your platform's native secrets management (e.g. Kubernetes Secrets, AWS Parameter Store, Cloudflare Worker secrets). A .env file on a server is a plain-text liability.
  • Parser inconsistencies — The dotenv format has no formal spec. Behavior differs between dotenv, dotenvx, Docker, and shell sourcing — see the .env file syntax reference for the full per-parser comparison. Always test with your specific parser.

If your variables are unexpectedly undefined at runtime, the most common causes — load order, working directory, production overrides — are walked through in the dotenv not loading debugging guide.

How do you share .env files securely?

Never paste a .env into Slack, email, Discord, or a ticket comment — those channels keep the message indexed forever and sync it to every device the recipient ever signs into. The zero-friction option is send.env.dev: paste the file, get a single-use link, share it, and the link burns on first read. Encryption happens in your browser (the URL fragment carries the key, which browsers never send to servers), hosting is in the EU, and there is no account or CLI to install.

For continuous secret distribution to running apps and CI — not one-off hand-offs — you want a secrets manager instead: 1Password / Bitwarden CLI under 20 people, Doppler or Infisical past that, HashiCorp Vault when compliance demands dynamic credentials. The full sharing guide compares all of them with cost, security, and setup-effort columns.

References

Where can I learn more about environment variables?

Was this helpful?

Read next

The Complete .env File Syntax Reference

.env file syntax reference: quoting, comments, multiline values, variable expansion, and the parser differences across Node.js, Python, Ruby, Go, and Docker.

Continue →

Frequently Asked Questions

What is a .env file?

A .env file is a plain text configuration file that stores environment variables as KEY=VALUE pairs. It is used to keep sensitive configuration like API keys, database URLs, and feature flags out of source code.

Should .env files be committed to Git?

No. The .env file should be listed in .gitignore to avoid exposing secrets. Instead, commit a .env.example file with placeholder values so team members know which variables are required.

Can .env files have comments?

Yes. Lines starting with # are treated as comments in most dotenv implementations. Inline comments (KEY=value # comment) are supported by some libraries but not all — avoid them for portability.

What is the dotenv library?

dotenv is a library (available for Node.js, Python, Ruby, and other languages) that reads a .env file and loads its variables into the process environment. It is typically called at application startup before accessing any environment variables.

Stay up to date

Get notified about new guides, tools, and cheatsheets.