From the notebook
Where do your environment variables go when you deploy?
Secrets pasted into Vercel or Render are not bundled into your build. They take a separate path and are injected at runtime, with one Next.js exception. Part 5.
When you paste an API key into a platform dashboard like Vercel or Render, it is not bundled into your application. Your code and your secrets travel separately: code goes through the build and becomes an artifact, while secrets go into an encrypted secret store and are injected into the process environment when the app starts. The big exception: in Next.js, any variable prefixed NEXT_PUBLIC_ is written into the browser bundle, and is therefore public.
Part 5 of the Modern Deployments series. Previous: what actually gets deployed.
Is my API key inside the Docker image?
The first time I pasted an OPENAI_API_KEY into a dashboard and clicked deploy, I wondered: is this bundled with my app? Is it baked into an image someone could pull and read? Have I just uploaded my .env to a server that could leak it?
For runtime variables on a properly set up platform, the answer is usually no.
How do code and secrets travel?
They follow two separate paths that meet only when your app starts:
Code: git push → build → compile and bundle → artifact Secrets: dashboard → encrypted secret store → runtime injection → process.env
When your Node.js process boots, the platform has already authenticated the deployment, fetched the secrets for that project and environment, and placed them in the process environment. That’s why process.env.DATABASE_URL just works even though it was never in your bundle.
Why does this separation matter?
It’s what makes immutable deployments practical. You can promote the exact same artifact from development to staging to production and attach different configuration to each. The build doesn’t change; only the configuration attached at startup does.
What’s the Next.js exception?
Anything prefixed NEXT_PUBLIC_ is inlined into the client-side JavaScript at build time. Two consequences:
- It isn’t a secret anymore. Every browser that loads your site downloads it. Never put a private key behind
NEXT_PUBLIC_. - It’s baked into the artifact. Changing it needs a rebuild, not just a restart.
Other frameworks have the same idea with different prefixes, such as VITE_ in Vite.
How do you keep deployment secrets safe?
- Keep secrets server-side. If the browser needs data from a paid API, proxy the call through your backend.
- Use your platform’s “sensitive” setting where it exists, so values can’t be read back from the dashboard later.
- Scope secrets per environment. Preview deployments shouldn’t hold production database credentials.
- Rotate after any doubt. Rotate when someone leaves, when a third-party integration is compromised, or when a key was ever committed to git.
- Audit third-party access. OAuth apps and integrations with access to your platform account can read what you can.
Once you see the artifact and its configuration as two separate lifecycles, a lot of cloud infrastructure clicks into place.
The full series
- How free tiers work
- Your app runs on a desired state
- Serverless cold starts
- What gets deployed to production
- Where environment variables go (this post)