# Production Environment Variables

> A step-by-step workflow for building a complete, valid production environment configuration using the Dev Tool's Environment Variables manager.

*Canonical: https://makerkit.dev/docs/tanstack-drizzle/dev-tools/production-environment-variables*

---

Getting production environment variables right is one of the most error-prone parts of shipping a SaaS app: a single missing secret, a leftover development URL, or a value that fails validation can break authentication, billing, or email in production. The Dev Tool's **Environment Variables** manager turns this into a checklist you can work through visually.

This guide walks you through building a correct production configuration. It assumes you have the Dev Tool running (`pnpm --filter dev-tool dev`) and open at [http://localhost:3010/variables](http://localhost:3010/variables). If you haven't used the manager before, read [Environment Variables](environment-variables) first.

{% callout type="warning" title="Never commit production secrets" %}
This workflow prepares production **values** and validates them locally. Real production secrets (API keys, database URLs, signing secrets) belong in your hosting platform's environment settings — not in any committed file. The Dev Tool writes secrets only to git-ignored `*.local` files so you can test locally without leaking them.
{% /callout %}

## Step 1 — Switch to Production Mode

Use the **mode selector** at the top-left and choose **production**. Everything on the page now reflects the production file chain, where later files win:

```text
.env → .env.production → .env.local → .env.production.local
```

This matters because a value that looks correct in development may be shadowed (or missing) in production. Working in production mode shows you exactly what your production build will see.

## Step 2 — Fix Every Invalid Variable

Click the **Display Invalid only** toggle (or filter by **invalid**). The manager validates each value against its schema — URLs must be URLs, ports must be numbers, enums must be one of the allowed values, and required variables must be present.

Work down the list until the **Invalid** chip reads `0`. Common production fixes:

- **`VITE_SITE_URL`** — set to your real HTTPS domain (e.g. `https://app.example.com`), not `http://localhost:3000`. Many features (emails, OAuth redirects, absolute links) derive URLs from this.
- **Auth secrets** — provide the production values for your auth provider and any social providers you enabled.
- **Billing** — set the production keys and webhook secrets for your billing provider (Stripe or Polar).
- **Email/SMTP** — set the production `EMAIL_*` values so transactional email works. You can verify these end-to-end from the Dev Tool's **Emails** page.

## Step 3 — Confirm Required Variables Are Present

Filter the list so you can scan the **Required** badges. A required variable with no effective value in production mode is a deployment blocker. Because production mode already excludes development-only files, anything still empty here will be empty in production too.

## Step 4 — Review the Override Chain for Surprises

Filter by **overridden** and inspect each variable's **Override Chain**. Overrides are where subtle production bugs hide:

- A development value in `.env.local` can leak into production because `.env.local` loads in *both* modes.
- A committed `.env` default may be silently overriding a value you intended to set per-mode.

For each overridden variable, confirm the *winning* file is the one you want for production. If a development-only value is winning, move it: put the production value in `.env.production` (public) or `.env.production.local` (secret), or remove the stray override.

## Step 5 — Separate Public and Secret Values Correctly

Check each variable's **Public** / **Private** tag:

- **Public** variables are `VITE_`-prefixed and **inlined into the client bundle**. Never put a secret in a `VITE_` variable — it ships to every browser.
- **Private** variables are server-only and safe for secrets.

When you edit a value in production mode, the Dev Tool automatically routes it to the right file:

| Value type | Written to |
| --- | --- |
| Public (`VITE_`) | `apps/web/.env.production` |
| Secret / private | `apps/web/.env.production.local` (git-ignored) |

So public production defaults become part of your committed config, while secrets stay local and out of git.

## Step 6 — Export the Final Configuration

Once the **Invalid** chip is `0` and every required and overridden variable checks out, use **Copy env file to clipboard** (top-right). This copies the fully-resolved production configuration in `KEY=value` form.

Paste it into your hosting platform's environment settings:

- Keep only the values production actually needs — you generally do **not** paste public defaults that are already committed in `.env`.
- **Always** set secret values (auth, database, billing, email) directly in the platform, never in a committed file.

See [Environment Setup](../going-to-production/environment-setup) and [Deployment](../going-to-production/deployment) for platform-specific steps.

## Step 7 — Verify Before You Ship

Before deploying, do a final pass in the Dev Tool:

- **Invalid = 0** in production mode.
- No `localhost` or development URLs remain in `VITE_SITE_URL` or related variables.
- No secret sits in a `VITE_`-prefixed variable.
- Every required variable resolves to a value.
- The **Emails** page can render and send a test email with your production SMTP settings.

## Quick Reference

| Goal | In the Dev Tool |
| --- | --- |
| See production values | Mode selector → **production** |
| Find broken values | **Display Invalid only** / filter **invalid** |
| Find missing required values | Scan **Required** badges |
| Spot shadowed values | Filter **overridden** → check **Override Chain** |
| Avoid leaking secrets | Check **Public/Private** tag; keep secrets out of `VITE_` |
| Export config | **Copy env file to clipboard** |

For the full catalog of every variable and its meaning, see [Environment Variables Reference](../configuration/environment-variables).
