Close password registration on the server, update the sign-in UI, and preserve existing-account access without assuming a complete invitation policy.

To stop new email/password registrations in BTST while keeping existing users able to sign in, disable registration on the Better Auth server and hide sign-up in the companion UI. The server setting enforces the policy when someone calls the API directly.
This guide targets better-auth@1.6.16, @btst/better-auth-ui@2.0.1, and @btst/stack@3.1.2. It extends an existing installation. Follow the integration guide or companion documentation first if you are still configuring routes and sessions.
The recipe below closes the email/password sign-up endpoint. It does not establish an application-wide invitation policy. Social providers, magic links, email OTP, administrator-created accounts, and your own provisioning code can have separate account-creation rules.
Before calling a product “invite only,” inventory every enabled path that can create a user. Define who may provision an account, how invitation ownership is verified, and where that decision is enforced. An organization invitation normally grants membership to an authenticated user; it is not automatically permission to create a new application account through a closed registration endpoint.
Keep emailAndPassword.enabled true so existing users can still sign in. Add disableSignUp: true to that configuration:
import type { BetterAuthOptions } from "better-auth";
export const closedPasswordRegistration = {
enabled: true,
disableSignUp: true,
} satisfies NonNullable<BetterAuthOptions["emailAndPassword"]>;
Merge this object into your existing server configuration as emailAndPassword: { ...existingEmailAndPasswordOptions, ...closedPasswordRegistration }. Preserve password rules, email verification, reset-password delivery, database adapters, plugins, and all other application settings. This object is a configuration fragment, not a replacement auth server.
In the pinned Better Auth release, a request to /sign-up/email is refused with a 400 response and the EMAIL_PASSWORD_SIGN_UP_DISABLED code when this setting is enabled. Check that the rejected request leaves no new user or account record. Your handler's usual API mount still applies: a default deployment receives the request at /api/auth/sign-up/email.
Do not rely on removing a link, hiding a component with CSS, or redirecting the page. Those changes cannot prevent a direct API request.
Merge this fragment into overrides.auth in your existing StackProvider, keeping its client and callbacks:
import type { AuthPluginOverrides } from "@btst/better-auth-ui/client";
export const closedRegistrationUI = {
signUp: false,
pageProps: {
signIn: {
localization: {
SIGN_IN_DESCRIPTION: "Sign in with your existing account.",
},
},
},
} satisfies Pick<AuthPluginOverrides, "signUp" | "pageProps">;
If you already customize pageProps, merge the sign-in changes into that nested object instead of dropping its other pages. The released companion suppresses the sign-up affordance and treats the sign-up form as an invalid view when sign-up is disabled. Check a direct visit to your sign-up URL as well as the link on the sign-in page.
Make the surrounding product copy accurate. A waitlist or support link can explain how access is granted if that process exists. Do not promise an invitation workflow that your server does not implement.
Use a test account created before enabling the restriction. Confirm that its correct password still signs in, an incorrect password fails, and the password-reset flow remains available. Existing sessions should continue following your normal session policy; changing this flag is not an instruction to delete accounts or revoke sessions.
Then test a new email address against the sign-up API with the UI bypassed. Confirm the rejection and unchanged database state. Repeat the account-creation checks for any other enabled sign-in methods under their own policy. Merely hiding those buttons does not turn off their endpoints.
Finally, test a real invitation flow in a disposable organization. An existing user should authenticate before accepting membership. If invited people must first create accounts, you need a separate, validated provisioning design; do not temporarily reopen public registration around an invitation request.
The organization setup guide covers invitations and membership UI. The sign-in customization guide explains page-specific copy, while password reset covers recovery for existing accounts.
Sources: Better Auth email/password options, the pinned sign-up endpoint, and the released companion's auth overrides, auth form, and auth view.