Documentation

Everything you need to get up and running with DotEnv

Multiple Environments

3 min read 1 views

Multiple Environments

Real projects have more than one set of secrets: production, staging, and development at least, often several services within each. DotEnv models this with a three-level hierarchy so you can keep shared values in one place and override only what differs per stage.

The hierarchy

Every path has the form:

project/target/environment
  • project — the application (e.g. myapp).
  • target — a deployment stage (e.g. production, staging, development).
  • environment — a service or context within that stage (e.g. api, worker, web).

Values set on a shallower level are inherited by everything beneath them. A secret defined on the project applies to every target and environment unless a deeper level redefines it.

nginx
myapp                       # shared by everything
myapp/production            # shared by all production environments
myapp/production/api        # specific to the production API

Pull the right set per stage

dotenv pull merges the whole path — project → target → environment, deeper wins — into one flat .env:

bash
# Local development
dotenv pull myapp/development/local --output .env

# Staging deploy
dotenv pull myapp/staging/api --output .env --quiet

# Production deploy
dotenv pull myapp/production/api --output .env --quiet

Each command returns the fully merged values for that stage. You change one path segment to target a different environment — the rest of your pipeline stays identical.

Put shared values where they belong

Decide which level each secret lives on:

  • Project level — values identical everywhere (e.g. a feature flag default, a vendor's public API base URL).
  • Target level — values shared across a stage (e.g. the staging database host).
  • Environment level — values unique to one service (e.g. that service's queue name).

This keeps each value in exactly one place. Update the staging database host once at myapp/staging and every staging environment inherits it.

See what a level resolves to

Pull merges by default. To inspect only the values defined directly on a level (ignoring inherited parents), use --level-only:

bash
dotenv pull myapp/production/api --level-only

This is useful when you're deciding whether a value belongs higher up the tree. Browse the whole hierarchy with dotenv tree and dotenv explore (see the command reference).

Promote a value between stages

Pull from one stage and push to another using a file as the carrier:

bash
dotenv pull myapp/staging/api --output promote.env --level-only
dotenv push myapp/production/api promote.env
rm promote.env

Review the values before pushing — production usually needs different credentials than staging, so you'll typically edit promote.env first.

Where to go next

Was this article helpful?

Help us improve this article

Thank you for your feedback!

There was an error with your submission