An environment variable is a named value stored in a process’s environment that programs read to alter their behavior without changing code. Each running process holds a set of these key-value pairs, and when it launches a child process the child inherits a copy. Because they are read at startup and require no recompilation, environment variables are the standard mechanism for configuration such as file paths, feature flags, credentials, and locale settings across virtually every operating system and language.
Key takeaways
- Environment variables are per-process key-value pairs, inherited by child processes.
- They configure programs externally, keeping settings out of source code.
- On Unix-like systems, a value must be exported to become part of the environment.
- They do not persist across sessions unless written to a startup or system file.
PATHis the most important example: it tells the shell where to find commands.- They are convenient for secrets but can leak; treat high-value secrets with more care.
How do I read and set environment variables?
In a Unix-like shell you assign with NAME=value and read with $NAME. A plain assignment creates a shell variable visible only to the current shell. To make it visible to programs the shell launches, you must export it:
export API_URL="https://api.example.com"
echo "$API_URL"
To see the whole environment, run printenv or env. To remove a variable, use unset NAME. In Windows Command Prompt you use set NAME=value, and in PowerShell $Env:NAME = "value".
Setting a variable for one command only
You can scope a variable to a single command by prefixing the command with the assignment. This does not affect your shell afterward:
NODE_ENV=production node server.js
How does inheritance and scope actually work?
The environment is not global state; it belongs to each process. When a process forks a child, the child receives a snapshot copy. Two consequences follow that trip up many developers:
- A variable you export in one terminal is invisible in another terminal opened separately.
- A change a child process makes to its environment never propagates back to the parent.
This is why a script that sets a variable cannot change your interactive shell unless you source it (run it in the current shell with source script.sh or . script.sh) instead of executing it as a child.
How do I read environment variables from code?
Every mainstream language exposes the environment through a standard API. The values always arrive as strings, so you must parse numbers and booleans yourself.
// Node.js
const port = process.env.PORT || "3000";
# Python
import os
debug = os.environ.get("DEBUG", "false") == "true"
Note the two habits shown here: provide a default for optional variables, and explicitly convert the string when you need a non-string type. Treating "false" as a boolean without conversion is a classic bug because a non-empty string is truthy in most languages.
How do I make environment variables persist?
Interactive assignments disappear when the shell exits. To keep a variable available in future sessions, add the export line to a shell startup file. The correct file depends on the shell and whether the session is a login shell.
| Shell | Common file | Notes |
|---|---|---|
| bash | ~/.bashrc or ~/.bash_profile |
Login vs. interactive distinction matters |
| zsh | ~/.zshrc |
Default shell on modern macOS |
| fish | ~/.config/fish/config.fish |
Uses set -x instead of export |
For system-wide values, administrators use files under /etc or platform-specific settings. In containerized and cloud environments, variables are usually declared in the orchestration configuration rather than in shell files.
How are environment variables used in .env files and deployment?
Application projects commonly keep configuration in a file named .env that a library loads at startup. This keeps settings out of the codebase and lets each environment supply its own values:
DATABASE_URL=postgres://localhost/app
LOG_LEVEL=debug
Two rules keep this safe and reliable:
- Never commit a real
.envto version control. Commit a.env.examplewith dummy values instead, and add.envto.gitignore. - In production, prefer variables injected by the platform or a secrets manager over files on disk, so credentials are never written to the repository or image.
A related idea is precedence. When the same setting is defined in several places, later sources typically override earlier ones. A common order is built-in defaults, then a .env file, then real environment variables set by the shell or platform, so an operator can always override a file value without editing it. This layering is central to the widely followed practice of keeping configuration in the environment rather than in code, which makes the same build artifact deployable to development, staging, and production simply by changing the variables around it. In containerized deployments the same principle applies: an image ships with no secrets baked in, and the orchestrator supplies environment variables at run time, so one image serves every environment.
What are the security considerations?
Environment variables improve on hardcoded secrets, but they are not a vault. Be aware of the ways they leak:
- Process inspection. On many systems a user can read another process’s environment, and tools like
pscan expose values passed on a command line. - Child processes. Every subprocess inherits the full environment, so a secret meant for one program is visible to everything it spawns.
- Logs and crash reports. Frameworks that dump the environment on error can write secrets into log files.
For sensitive credentials, use a dedicated secrets manager, scope variables as narrowly as possible, and avoid passing secrets as command-line arguments, which are far more visible than the environment itself.
Which environment variables should every developer know?
A handful of variables are near-universal, and recognizing them saves a great deal of confusion when debugging tools and shells.
| Variable | Meaning |
|---|---|
PATH |
Directories searched for executable commands |
HOME |
The current user’s home directory |
USER |
The current username |
SHELL |
Path to the user’s login shell |
PWD |
The current working directory |
LANG / LC_* |
Locale and character-encoding settings |
TERM |
The terminal type, affecting colors and control codes |
Applications add their own conventions. NODE_ENV signals whether a Node application runs in development or production; HTTP_PROXY and NO_PROXY steer network clients through or around a proxy; and many tools read a *_TOKEN or *_API_KEY variable for credentials. Because these are conventions rather than rules, always check a tool’s documentation for the exact names it reads.
Appending to PATH correctly
A common task is adding a directory to PATH without discarding the existing entries. Reference the old value when building the new one:
export PATH="$HOME/bin:$PATH"
Placing your directory first makes the shell prefer your binaries; placing it last ("$PATH:$HOME/bin") makes system binaries win. Forgetting to include $PATH at all is a serious mistake because it wipes out every standard command location for that session.
What are common mistakes with environment variables?
- Forgetting to export. A variable set without
exportis invisible to the program you run next. - Expecting non-string types. Every value is a string; parse it before using it as a number or boolean.
- Quoting problems. Values with spaces or special characters need quotes, both when set and when referenced as
"$NAME". - Assuming persistence. Changes vanish on shell exit unless written to a startup file.
- Committing secrets. A
.envfile checked into a repository is a common and serious leak.
Frequently asked questions
Are environment variables global to the whole system?
No. Each process has its own environment, inherited from its parent. Setting a variable in one shell does not change it in unrelated processes or other users’ sessions.
Do environment variables persist after I close the terminal?
Not by default. Variables set interactively vanish when the shell exits. To persist them you add the assignment to a shell startup file or a system configuration.
Are environment variable names case sensitive?
On Unix-like systems they are case sensitive, and the convention is uppercase names. On Windows the names are case insensitive.
Can environment variables store secrets safely?
They are better than hardcoding secrets in source, but they can leak through process listings, crash dumps, and logs. For high-value secrets prefer a dedicated secrets manager.
What is the difference between a shell variable and an environment variable?
A shell variable exists only in the current shell. It becomes an environment variable, visible to child processes, only when you export it.
How does a child process get environment variables?
When a process starts a child, the child receives a copy of the parent’s environment. Changes the child makes do not flow back to the parent.
What is the PATH variable?
PATH is an environment variable holding a list of directories the shell searches, in order, to find executable programs when you type a command name.