Deployment names
The names that live where the functions run, how to set them, and what each one switches on.
These twelve are read by the Convex deployment: the schema, the functions, the scheduled work and the authentication. They are not a file. They are set on the deployment itself, and the command that sets one is the same on your laptop and on a server.
npx convex env set NAME "value" # the development deployment
npx convex env set NAME "value" --prod # the production deployment
npx convex env list # which names are set (never the values)The accounts and the sessions
Prop
Type
BETTER_AUTH_SECRET signs the session token that travels with every request, which is what makes a signed-in
browser a signed-in browser. It is read where the sessions are created, so it belongs to the deployment and
not to the app. Rotating it is a deliberate act: everybody, including you, is signed out and signs in again.
SITE_URL is the same address as NEXT_PUBLIC_APP_URL, written where the deployment can read it. The
deployment builds the links it puts in emails itself, so it needs its own copy.
The three ADMIN_ names are only read by the bootstrap command, once:
npx convex env set ADMIN_EMAIL "you@your-domain.com"
npx convex env set ADMIN_PASSWORD "a long one"
npx convex env set ADMIN_NAME "Your Name"
npx convex run admin:bootstrapThese three stay in the environment after the bootstrap
They are read only when the command runs, but they are still readable by anybody with access to the deployment's settings. Once the first administrator exists, the honest thing to do is change their password from inside the product and leave the shipped one as a value that no longer opens anything.
The two sign-in providers
Prop
Type
Both pairs are optional. With neither, the sign-in screen still offers both buttons, and pressing one says the provider is not configured on this installation, which is a better answer than a button that does nothing.
The two flows are written out screen by screen in Google sign in and GitHub sign in, including the exact callback addresses to paste into each console.
Prop
Type
Without these, confirmation and reset codes are not sent. Sign in by password still works for accounts that are already confirmed. Email that arrives covers the domain verification that makes the difference between "sent" and "delivered".
The spend ceiling
Prop
Type
Optional, and the second of the two optional names in the whole list. It exists for the case where the
installation itself has a budget that has nothing to do with what any plan allows. Money → Credits holds the
interactive version of the same ceiling, and that is where most installations set it.
Sets, and why one of them changes what users can do
| Name | What it switches on when set |
|---|---|
BETTER_AUTH_SECRET | Sessions that survive a refresh |
SITE_URL | Correct links inside emails |
ADMIN_EMAIL + ADMIN_PASSWORD | The first administrator, once |
GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET | The Google button signs people in |
GITHUB_CLIENT_ID + GITHUB_CLIENT_SECRET | The GitHub button signs people in |
RESEND_API_KEY + EMAIL_FROM | Confirmation and reset codes arrive |
CREDIT_MONTHLY_CAP | A ceiling above every plan |
A name set on the wrong deployment
--prod is easy to forget. Setting a name on a development deployment and
then deploying to production leaves production without it, and the symptom is
a feature that works on your laptop and not on the server. npx convex env list --prod is the check.

