> ## Documentation Index
> Fetch the complete documentation index at: https://help.the-meridian.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment variables

Your app's configuration (API keys, connection strings, and other settings) is managed as environment variables and secrets, injected into your app at deploy time. Meridian stores secret values in Google Secret Manager. Values you save as secrets here are write-only and cannot be read back.

You do not need a connected GitHub repository to set them. On an app with no repository and no deploy yet, the Hosting overview asks you to connect GitHub and links to this page, so you can prepare variables and secrets before the first deploy, which reads them.

## Variables and secrets

A variable is either a plain value or a secret:

* **Plain variables** are readable back in the dashboard by the organization that set them.
* **Secrets you set** are write-only: once saved, the value is never returned in an API response, logged, or shown again. Meridian keeps only a reference to the version in Secret Manager.

Keys are uppercase in the `ENV` format (`^[A-Z][A-Z0-9_]*$`, up to 128 characters). Meridian normalizes them for you.

## Scope and precedence

Each variable or secret you add on the **Environment** page has a scope, shown in its **Scope** column. Pick it with the toggle next to **Variable / Secret** when you add the entry. It lists **All environments** and then each environment the app has:

* **All environments** (the default) applies to every environment of the app: Development, Staging and Production. Use it for values that are the same everywhere.
* **Production**, **Staging** or **Development** applies to that environment only, shown as **Only Production** (and so on) in the Scope column. You can add a value for any environment from any tab: a value for another environment is saved there and shows on that environment's tab. An environment your plan includes but that does not exist yet is greyed out until it is created. Use it for values that differ per environment, such as `SHOPIFY_APP_URL` or a sandbox API key.

When the same key is set for all environments and only for this environment, the **environment value wins** at deploy. The table shows both rows. The shared one is struck through with an **Overridden here** badge, and it still applies to the other environments. Delete the override to go back to the shared value in that environment, then redeploy.

A key can exist once per scope. Adding a key that already exists in the same scope is refused, so edit the existing entry instead. Entries you set before scopes existed are **All environments** entries and behave as before.

[Bringing a build forward](/environments#bringing-a-build-forward) does not copy values that are set only for the source environment. The confirm dialog lists any key set only for the source that the target does not have, so you can add it for the target first.

## When changes take effect

Adding, editing or deleting a variable or secret doesn't touch the running app. The change reaches it with the next deploy, which creates a new revision with the current values. A change to an **All environments** entry concerns every environment of the app.

The same goes for the other settings a deploy reads: the Shopify credentials on the [settings page](/app-settings), a rotated API key or webhook signing secret (the change concerns every environment of the app), and an environment's health check path and release command. Saving the same value again is not a change. Capacity changes and add-ons are not on this list: they update the live service on their own. See [Configuration takes effect on deploy](/environments#configuration-takes-effect-on-deploy).

Until a deploy starts, **Secrets and variables** and the **Hosting** overview show **Changes apply on the next deploy.** on the tab of each environment the change concerns. Members who can deploy to that environment also get **Deploy now**, which redeploys that environment's live commit with the current values and settings after you confirm. On production that needs the **hosting.promote** [permission](/customer-permissions), like any production deploy. It reuses that commit's build when its image still exists, so it is quick and ships no new code. Any deploy started after your change clears the banner too, including an automatic one from a push or a build [brought forward](/environments#bringing-a-build-forward) from another environment.

The banner comes back if that deploy fails or is cancelled, because the previous revision keeps serving with the previous values. It also comes back after a [rollback](/deployment#rollback) to a release deployed before your change, since the restored revision runs with the values it was deployed with.

One nuance for secrets: after you replace a secret's value, instances that start later (when the app scales out or wakes from zero) can already read the new value, while instances already running keep the old one. Deploy to move every instance to the new value at once.

## Managed variables

Meridian also injects its own variables at deploy time. You don't set these; they're provided.

| Set | Comes from |
| - | - |
| `SHOPIFY_API_KEY`, `SHOPIFY_API_SECRET` | The Shopify credentials on the app's [settings page](/app-settings) |
| `MERIDIAN_APP_ID`, `MERIDIAN_API_URL`, `MERIDIAN_OAUTH_CLIENT_ID`, `MERIDIAN_OAUTH_CLIENT_SECRET` | The app's platform identifiers and hosting OAuth credentials |
| `MERIDIAN_API_KEY`, `MERIDIAN_WEBHOOK_SECRET` | An automatically created hosting SDK key and the app's current webhook signing secret |
| `DB_*` | The environment's managed [database](/database) |
| `REDIS_URL`, `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD` | The [Redis](/redis) add-on |
| `CRON_SECRET` | The [scheduler](/scheduler) add-on |
| `STORAGE_BUCKET`, `STORAGE_LOCATION`, `STORAGE_PUBLIC_URL` | The [object storage](/storage) add-on |
| `CDN_URL` | The [CDN](/cdn) add-on, when the environment also has object storage |

Your own `MERIDIAN_API_KEY` or `MERIDIAN_WEBHOOK_SECRET` overrides the managed value. The same applies to the Shopify credential pair. Delete your override and redeploy to restore the managed value. Platform identifiers (`MERIDIAN_APP_ID`, `MERIDIAN_API_URL` and `MERIDIAN_OAUTH_CLIENT_ID/SECRET`) always use Meridian's values. See [SDK credentials](/sdk-credentials#on-meridian-hosting) for key rotation and redeployment.

Managed [database](/database) and [Redis](/redis) passwords can be revealed separately from their hosting screens. Those actions require access to credentials and are recorded in the organization audit log.

Your AI client can list the managed set (names only) through [Meridian MCP](/mcp-server) (`managed_variables_list`) so it doesn't write a workaround for a variable the platform already provides.

<Note>
  Because values you save as secrets are never read back, an agent or teammate can confirm a variable exists and is spelled correctly, but can never retrieve its value, which is what almost every "missing env var" check actually needs.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.