Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

Heroku Env Variables: The Config Vars, the .env Mismatch, the Secret Manager, and the Migration to Modern Platforms

Sean

Platform Writer

Jun 23, 2026
7 min read

Heroku env variables are config vars — key-value pairs set via the dashboard, the Heroku CLI, or the Heroku API, and injected into the running app’s environment as $VAR_NAME strings. The right answer is config vars for the secrets, .env for the local dev, and a secret manager (or platform equivalent) for the production rotation. The gotcha: the team’s .env file is checked into the repo (security incident), the team’s config vars are not in source control (deployment hazard), and the team’s secrets are not rotated (compliance gap).

Heroku Env Variables: The Config Vars, the .env Mismatch, the Secret Manager, and the Migration to Modern Platforms

Table of contents

The config vars — what they are and how to set them

A config var is a key-value pair that Heroku injects into the app’s environment at runtime. The team’s Node code reads process.env.DATABASE_URL, the team’s Python code reads os.environ['DATABASE_URL'], the team’s Go code reads os.Getenv("DATABASE_URL"). The config var is the runtime contract between the platform and the app.

The right answer to set a config var is heroku config:set DATABASE_URL=postgres://.... The right answer to list config vars is heroku config. The right answer to remove a config var is heroku config:unset DATABASE_URL. The right answer in the dashboard is Settings > Config Vars > Reveal Config Vars.

The .env mismatch — the team that ships a different config than the dev

The team that uses .env for local dev and config vars for production has a mismatch. The local .env has DATABASE_URL=postgres://localhost/..., the production config var has DATABASE_URL=postgres://prod-host/.... The team’s process.env.DATABASE_URL reads the right value in each environment — the abstraction is the same. The gotcha: when the team adds a new var, they add it to .env for dev but forget to add it to the config vars in production. The deploy breaks, the team’s on-call gets paged.

The right answer is to have a single source of truth for the list of env vars (a .env.example checked into the repo), to add new vars to the source of truth first, then to the .env and the config vars.

The secret manager — when config vars are not enough

Config vars are not a secret manager. The config var is a string in Heroku’s database, the team’s CI can see it (with the right permissions), the team’s Heroku support team can see it. The right answer for a secret that needs rotation, audit, or fine-grained access is a real secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault). The right answer is to have the config var point to the secret manager, not to contain the secret directly.

The rotation — when config vars change and the app restarts

The team that updates a config var (heroku config:set DATABASE_URL=...) triggers an app restart. The new value is injected, the app restarts, the new connection string is used. The right answer is to plan the rotation during a low-traffic window — the restart takes 10-30 seconds, the team’s in-flight requests fail with 5xx.

The gotcha: the team that needs to rotate a secret without an app restart uses the secret manager pattern above. The app reads the secret at request time, not at startup, and a rotated secret is picked up immediately.

The migration to a modern platform — what changes and what stays

The team migrating from Heroku to a modern platform (Render, Fly, Railway, a Kubernetes-based PaaS) keeps the abstraction. The new platform has env vars (Render: Environment, Fly: secrets, Railway: Variables), the env vars are injected at runtime, the team’s code reads process.env.VAR_NAME the same way. The migration is a config export (heroku config > .env) and a config import (paste the values into the new platform’s dashboard).

The gotcha: the new platform’s env var name might be different (DATABASE_URL vs. DB_URL vs. POSTGRES_URL). The team should standardize the names in the code first, then port the values.

The audit — what config vars are set, and who set them

The right answer for a config var audit is to run heroku config and compare against the list of expected vars (the .env.example plus the platform-specific vars). The team that has a config var that is not in the code is a dead var. The team that has a code var that is not in the config is a deploy hazard.

The right answer for the team’s compliance audit is to log every config var change (Heroku does this by default), and to alert on changes outside the maintenance window.

How this fits the rest of the stack

The infrastructure question is a small piece of a larger pattern: the team’s runtime, storage, database, secret store, logs, and deployment platform are all parts of the same platform. The right answer is to model the full stack before the project ships, not after. The RunxBuild hosting calculator is the right place to do that exercise — pick the runtime, the memory tier, the storage, the secret store, and the egress, and the calculator shows what the deploy actually costs at the team’s actual usage.

Useful related references:

FAQ

How do I set env variables on Heroku?

heroku config:set KEY=value from the Heroku CLI, or Settings > Config Vars in the dashboard.

Where are Heroku env variables stored?

In the Heroku database, encrypted at rest. The team’s config vars are visible to anyone with heroku config access on the app.

Can I use a .env file on Heroku?

No — Heroku does not read .env files. The team’s local dev uses .env, the production uses config vars. Keep both in sync via a .env.example.

How do I rotate a Heroku config var?

heroku config:set KEY=newvalue triggers an app restart. The right answer for a secret that needs to be rotated without a restart is to use a secret manager.

What is the difference between Heroku config vars and a secret manager?

Config vars are a key-value store, not a secret manager. The right answer for a secret is a real secret manager with rotation, audit, and fine-grained access.

How do I migrate Heroku env variables to a new platform?

Export with heroku config > .env, then import the values into the new platform’s env var interface.

Do Heroku env variables survive a dyno restart?

Yes. The config vars are stored at the app level, not the dyno level.

How do I hide Heroku env variables in the build log?

Heroku automatically hides env vars that match common secret patterns. The right answer for a secret that the team needs to use in the build is to use a buildpack that reads the secret.

#Heroku#Env Variables#Secrets#Config Vars#Platform