Environment variables
Encrypted at rest, scoped precisely, available at build time and runtime.
Scopes & precedence
Per key, the most specific definition wins:
| Precedence | Scope | Applies to |
|---|---|---|
| 1 (highest) | App + branch | One app, one branch |
| 2 | App | One app, every branch |
| 3 | Shared + branch | Every app, one branch |
| 4 | Shared | Every app in the project |
Shared variables flow to every app of the project — a DATABASE_URL defined once reaches the web app and the worker. Define an app-scoped row with the same key to override it for that app only. One app's scoped variables are invisible to the others.
Secrets
- All values are encrypted at rest (AES-256-GCM).
- Secret-marked values additionally never enter container image layers: at build time they are provided through BuildKit secret mounts; at runtime through the orchestrator's secret store.
- Names that look sensitive (
*_SECRET,*_API_KEY,*_PASSWORD,*_TOKEN,*_PRIVATE_KEY,*_SERVICE_KEY…) get secret handling automatically. Public prefixes (NEXT_PUBLIC_,VITE_,REACT_APP_,NUXT_PUBLIC_) are always treated as plain.
Build time vs runtime
Every variable is available during the build (framework prerendering, codegen) and at runtime. Remember that changing a variable takes effect on the next deploy — frameworks that inline values at build time (all NEXT_PUBLIC_* usage) need a rebuild to pick up changes.
Bulk import
Paste an entire .env file — in the project creation wizard, or any time into the add-variable dialog:
DATABASE_URL=postgres://user:pass@host:5432/db RESEND_API_KEY=re_xxxxxxxxxxxx NEXT_PUBLIC_SITE_URL=https://example.com
Keys and values parse like dotenv (quotes stripped, comments ignored). Empty values are allowed.
.env in the repo is not read at runtime.