Production Environment
Run your live app with its own secrets, database and settings, separate from development.
Your project runs in two places. The sandbox is development: the agent builds and tests there, using the values in your project's .env and the Secrets tab. Vercel or Railway is production: your live app runs there, using the environment variables stored on that host.
The two should never share secrets. This page covers why, and what to do after every deploy.
Why Production Needs Its Own Secrets
Contain leaks
Development keys pass through the sandbox, the terminal and the agent. If one leaks, production stays untouched.
Keep test data out
A separate production database means test sign-ups, seed rows and experiments never mix with real users.
Rotate independently
Replace a production key without breaking development, and the other way round.
Payments make this concrete: development runs on test credentials, where no money moves. Production needs live credentials, which only you set, directly on your host.
Never commit .env to your repository or paste its values anywhere, including
the chat. It holds your development secrets, and production reads its values
from the host, not from a file.
Rules for Every Variable
- Keep secrets out of the browser. Anything with a public prefix (
NEXT_PUBLIC_…in Next.js,VITE_…in Vite) is visible to every visitor. Only public values, like a payment provider's key ID, belong there. - Document names, not values. Keep a
.env.examplelisting every variable name with empty values, so you and collaborators know what production needs. - Never log secrets. Keep them out of console output, error messages and analytics.
- Use the narrowest key. When a provider offers restricted, read-only or scoped keys, use those instead of full-access ones.
- Share through the host. Give teammates access on Vercel or Railway instead of sending values over chat or email.
How Publish Handles Variables
Each deploy from Ideavo sends your project's current variables with it, and they replace matching variables on Vercel or Railway. That gets the first deploy running, but it also means your production values are overwritten on every deploy from Ideavo.
After every deploy from Ideavo, check your production variables on Vercel or Railway and update them again.
Updating Variables on Your Host
Open your host's environment variables, update the values, and redeploy so they take effect.
Open your project's Settings → Environments and choose Production.
Update the values under Environment Variables (Vercel's guide).
Redeploy from Deployments → ⋯ → Redeploy.
Browser variables (NEXT_PUBLIC_… in Next.js, VITE_… in Vite) are built into the app, so they change only after a new build.
Database in Production
Production needs its own database: ideally a new one, or at least a new branch of your development database.
- Create it and set its connection string as
DATABASE_URLon your host. - Apply your schema to it with your project's migration command, pointed at the production database.
- Repeat step 2 whenever a deploy changes the schema.
Never reset or seed the production database.
Auth in Production
If your app uses Better Auth, set these on your host:
BETTER_AUTH_SECRET: a new random value, different from development. Generate one withopenssl rand -base64 32. Changing it later signs every user out.BETTER_AUTH_URL: your production URL, such ashttps://your-app.vercel.appor your custom domain.- Social sign-in: in each provider's console (Google, GitHub and so on), add your production callback URL,
https://<your domain>/api/auth/callback/<provider>.
Payments in Production
Development payments run in test mode through Ideavo's connection. To accept real payments, you replace the test credentials with your own live keys on your host and register a separate live webhook. Ideavo never stores live credentials.
For Razorpay, follow the step-by-step guide in Razorpay → Going Live.
After Every Deploy
Run through these in order, top to bottom:
Restore production values. The deploy replaced them with development ones, so set them again on your host, and make sure every variable your app needs is there.
Migrate the database. If the schema changed, apply the migrations to the production database.
Check URLs. Every variable that holds a URL, such as BETTER_AUTH_URL,
sign-in callbacks and webhook endpoints, points at the live domain,
including a custom domain.
Check payments. Live keys are set, and the live webhook is registered.
Try it live. Sign in and complete your app's main flow on the live URL.
If a Secret Leaks
A secret is leaked the moment it lands somewhere it shouldn't: a commit, a chat, a screenshot, a public log. Deleting it from there doesn't make it safe, because it may already be copied.
Revoke it at the provider first. Generate a new key and delete the old one, for example regenerate API keys in the Razorpay Dashboard or reset the database password in Neon.
Set the new value on your host and redeploy. For a development secret, update it in the Secrets tab instead.
Check for misuse. Look through the provider's logs for activity you don't recognise, such as unexpected payments or database access.
Rotating BETTER_AUTH_SECRET signs every user out. That's expected: it
invalidates any session made with the leaked secret.