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.
DATABASE_HOST=localhost
PORT=3000Quoted values
Double quotes allow spaces and special characters. Single quotes treat the value as a literal string with no interpolation.
GREETING="Hello, World!"
REGEX='\d+\.\d+'Comments and empty values
Lines starting with # are comments. KEY= sets an empty string, as does KEY="".
# Database config
DB_PASSWORD=
DB_NAME=""Multiline and variable expansion
Some parsers support multiline values in double quotes and variable expansion with ${} syntax.
PRIVATE_KEY="-----BEGIN RSA KEY-----
MIIBogIBAAJBALRi...
-----END RSA KEY-----"
BASE_URL=https://api.example.com
FULL_URL=${BASE_URL}/v1/usersFor 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:
# 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=trueHow 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:
| Language | Setup | Access |
|---|---|---|
| Node.js | import 'dotenv/config' | process.env.KEY |
| Python | from dotenv import load_dotenv | os.getenv('KEY') |
| Go | godotenv.Load() | os.Getenv("KEY") |
| Docker | env_file: .env in compose | Injected into container environment |
What are .env file best practices?
- Never commit .env to git. Add it to your
.gitignoreimmediately. Leaked secrets are the number one cause of security incidents. - Provide a
.env.example. Commit a template file with dummy values so new team members know which variables are required. - Validate at startup. Fail fast if a required variable is missing or malformed. Libraries like
envalid(Node.js) orpydantic-settings(Python) make this easy. - Use typed configuration objects. Instead of sprinkling
process.env.Xthroughout your codebase, parse variables into a typed config object at the entry point. - Separate secrets from config. Non-sensitive values like
PORTorLOG_LEVELcan 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. - Use per-environment files. Many frameworks support
.env.development,.env.production, and.env.testto keep environments cleanly separated.
What are common .env file pitfalls?
- Whitespace around = —
KEY = valuewill break most parsers. Always useKEY=valuewith no spaces. - Unquoted values with # —
URL=https://x.com#anchorwill 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
.envfile 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
- motdotla/dotenv (Node.js) — the original library that popularised the .env pattern.
- dotenvx — encrypted .env files from the same author, designed to be safe to commit.
- 12-Factor App: Config — the methodology that says config belongs in the environment, not the codebase.
- Dotenvy file-format reference — the closest thing to a written spec for the dotenv format, including escape and interpolation rules.
- Docker Compose env file documentation — how Compose interpolates and resolves variables from
.env.
Where can I learn more about environment variables?
Ready to go further? Explore these resources: