Environment variables
Variables are scoped to an environment, so a production value never leaks into development. Files your app needs to read from disk are handled separately, as secret files.
Setting variables
Variables can be set when you create a service, and edited afterwards from its Variables tab. Each has a key, a value, and a scope.

For a long list, the bulk editor accepts KEY=value lines pasted straight from a
local .env file, which is faster than adding them one at a time.
Scoping
A variable is scoped either to one environment or to all environments:
| Scope | Visible in |
|---|---|
| A single environment | Only that environment |
| All environments | Every environment in the project |
Scope to a single environment for anything that differs per stage, like a database URL, a payment key or a log level. Scope to all environments only for values that are genuinely identical everywhere.
Values are masked in the interface once saved. Reveal a value deliberately when you need it. We never print it in logs, though your own application can of course log it.
Changing a variable restarts the service
Saving a variable change restarts the service with the new value, because a process reads its environment once at startup.
Set the variable before you deploy the code that reads it. Deploying code that expects a variable that does not exist yet gives you a crash loop until the value lands.
Secret files
Some configuration is not a string. A service account JSON, a private key or a certificate chain all go in Secret files instead: you give a path and contents, and the file is written into the container at runtime.
.env
credentials.json
certs/client.pemContents are not written into the built image, so they are not baked into anything you might later export.
Read them from your application the way you would read any file:
const creds = JSON.parse(
await readFile(new URL('./credentials.json', import.meta.url), 'utf8'),
);Variables you get automatically
Some values are supplied for you:
PORT, the port your service must listen on. See Builds & start commands.
Connection strings are not among them. A database or cache in the same
environment is reachable over the private network, but your app only gets its
URL once you add it as a variable. The Variables tab lists the databases
and caches in the environment, each with Add as DATABASE_URL (or
REDIS_URL), which saves its internal URL as a variable on the service. If the
key already holds something else, you are asked before it is replaced. See
Connecting to a database.
Time zone
Your service runs in UTC, so a timestamp your app writes into its own log
lines is UTC time. The time column in the dashboard's logs is always shown in
your browser's time zone. To make your app's own timestamps local too, set
TZ to a zone name, for example TZ=Africa/Lagos. Node.js honours it out of
the box; some other runtimes need time zone data in the image (the tzdata
package).