Set configuration and secrets per application, override them per environment, and bulk edit everything as a .env file in the console.
Environment variables
Set configuration values and secrets for an application, and override them per environment.
Per app and per environment#
Variables defined on the application apply to every environment. Each environment can override them or add its own, and at deploy time the environment's value wins:
| Defined on | Applies to | Wins when |
|---|---|---|
| Application | Every environment | No environment override exists |
| Environment | That environment only | Always |
That is how production keeps the real DATABASE_URL while a preview points at a test database.
In the console you edit variables on the environment's settings tab; anything inherited from the application is listed above the editable rows, so you can see the whole set an environment will run with.
Edit as a .env file#
The variables card has two modes. Form mode is one row per variable. Bulk edit is a textarea that speaks .env:
# comments and blank lines are fine
DATABASE_URL=postgres://appuser:secret@203.0.113.10:5432/mydb
API_KEY="sk-live-..."
export NODE_ENV=production
Paste a .env file straight in - quoted values, export prefixes, and KEY: value lines all parse, and the pasted set replaces the current one. Copy all goes the other way and puts the whole set on your clipboard as .env text.
When a save changes the set, the environment redeploys automatically, so the running service always matches what the console shows.
Build time and runtime#
- Static builds run your build command with the variables set, so values that get inlined at build time -
NEXT_PUBLIC_*,VITE_*, and friends - work as usual. - Container apps receive variables at runtime: read them from
process.env(or your language's equivalent) when the server starts. The container image itself is built without them, so don't bake configuration into a container build - read it at startup. See Builds. - On containers,
PORTis set for you (8080 by default) - listen on it and the routing works.
Common build-time prefixes, for reference:
| Framework | Inlined prefix |
|---|---|
| Next.js | NEXT_PUBLIC_ |
| Vite (React, Vue, Svelte, SolidJS, Qwik) | VITE_ |
| Create React App | REACT_APP_ |
| Gatsby | GATSBY_ |
| Astro | PUBLIC_ |
Anything inlined ships to the browser - never put secrets behind these prefixes.
From a .env file, automatically#
When you deploy from the VS Code extension or the MCP server, variables in your local .env file are read and set on the app for you. See Deploy with AI.
Database credentials#
Provision a database and its credentials tab gives you a ready connection string - set it as DATABASE_URL on the environments that should use it. The full wiring guide is Connect an app. WordPress apps can connect a database with one click instead, and stacks arrive pre-wired.
History without leaks#
Variable changes show up in the environment's activity history - which keys were added, removed, or changed, by whom, and when. Values are never written to the history, so the audit trail is not a credential leak.
Warning
Variables are the right place for secrets; the repository is not. Keep keys out of code and out of uploaded archives - anything in a static build's output directory is served publicly.