Why your environment variable disappears after you deploy
"It works locally" may be the most common sentence in deploy issues. The chatbot answers, the RAG app finds its documents, the agent calls its tools — and after the deploy the app crashes on startup or quietly returns an empty answer. The cause is often rather annoying: an environment variable that was on the laptop and isn't on the server.
We see this from the host side. At Hal9 we build Cloudish, a host for apps that AI agents deploy. Recently we indexed 1,608 public GitHub deploy issues into a dataset to learn what actually breaks. Environment variables turned out to be a real cause: about 7% of threads mention a missing environment variable. Admittedly, in this dataset, that doesn't constitute a big portion of problems — but it's a failure with a clear, satisfying fix.
Here is why a variable that works locally disappears after you deploy, and what to do about it.
Why the variable disappears only after deploy
First, .env doesn't travel to the server — and it shouldn't. The file belongs in .gitignore, and the values must be set separately in the host's settings.
Second, build time versus runtime. In Next.js, variables prefixed with NEXT_PUBLIC_ are inlined into the JavaScript bundle during next build and frozen after the build: ship one Docker image to several environments and they all keep the build-time value. Other variables are only available on the server. In Vite, variables prefixed with VITE_ are statically replaced at build time and end up in the client bundle, which is why the docs explicitly warn against putting API keys in them. Adding the prefix "to make it work" is the easiest way to publish your LLM API key in the browser.
Third, a new value does not apply to a deploy that is already running.
- On Vercel, environment-variable changes apply only to new deployments.
- On Render, "Save only" stores the values without deploying; the service keeps the old ones until its next deploy.
- On Railway, changes are staged and must be reviewed and deployed before they take effect.
- On Fly.io,
fly secrets setrestarts the Machines, and secrets are not available while the Docker image is built by default — build secrets are a separate mechanism. - On Cloudflare Workers,
wrangler secret putcreates and deploys a new Worker version immediately, and the docs tell you not to keep secrets in the Wrangler config'svars. - On Cloud Run, a Secret Manager secret exposed as an environment variable is read at instance startup: if the service account lacks the Secret Manager Secret Accessor role, the instance won't start, and Google recommends pinning a specific secret version instead of
latest. - Hugging Face Spaces has variables and secrets: variables are public and copied into duplicated Spaces; secrets are private and not copied.
- Netlify's Secrets Controller scans the repository and the build output, and fails the build if it finds the value of a marked secret.
The one that does leak — and how not to be it
Missing variables are common and boring. The scarier failure is rarer and worth a paragraph: a coding agent that deploys the whole project folder, .env and all. In our index it appears a handful of times — four, three of them AI-generated apps — too few to call a trend, but the mechanism is old and easy to trigger: whatever sits in the folder goes to the host unless something explicitly excludes it. An agent just does it faster and doesn't always ask.
GitHub scans public repositories for secrets for free, across the whole commit history, and account-level push protection blocks pushing a secret to a public repository by default. If a key did land in a repository, revoke and rotate it first; rewriting Git history is slow, and once the key is revoked GitHub itself says it is often unnecessary. Hugging Face likewise warns Space owners when its scanner finds hard-coded secrets.
For a coding agent, write the rules into the project's instructions (AGENTS.md, CLAUDE.md or the equivalent): keep a .env.example with variable names only; never read or log the contents of .env; don't write keys into code, and don't give secrets the NEXT_PUBLIC_ or VITE_ prefix; before deploying, show which files will go to the host and check .gitignore and .dockerignore; set secrets through the host's CLI or dashboard (vercel env add, fly secrets set, wrangler secret put) rather than through files in the project. An instruction to an agent is only a wish, so add a technical restriction as well: in Claude Code, for example, you can block reading .env with deny rules in settings.json.
Hopefully, you found some helpful pointers in this article. To be sure, every claim above was checked against the provider's own documentation on 5 November 2026. This article was prepared with help from an AI assistant. Cloudish, the host we build for apps that AI agents deploy, is at https://cloudish.ai.
