Installation
Requirements
- Node.js 20+
- Better Auth
^1.6.16 - A supported database adapter (Drizzle, Prisma, etc.)
Install the package
bash
pnpm add better-auth-tenancy better-authPeer dependencies:
@better-auth/corebetter-call
These are typically installed automatically with better-auth.
Server plugin
Import tenantAuth and add it to your Better Auth config:
ts
import { tenantAuth } from "better-auth-tenancy";
import { betterAuth } from "better-auth";
export const auth = betterAuth({
database: /* your adapter */,
secret: process.env.BETTER_AUTH_SECRET,
emailAndPassword: { enabled: true },
plugins: [tenantAuth()],
});Client plugin
Import tenantAuthClient from the /client export:
ts
import { tenantAuthClient } from "better-auth-tenancy/client";
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_APP_URL,
plugins: [tenantAuthClient()],
});The client plugin registers path methods and session listeners for tenant sign-in and sign-up endpoints.
Database schema
The plugin extends your Better Auth schema with:
tenant— tenant recordstenantOauthConfig— per-tenant OAuth credentialstenantIdonuser,session,account, andverification
Generate and apply the schema with the Better Auth CLI for your adapter. For example, with Drizzle:
bash
npx @better-auth/cli generate
# then push or migrate with your ORMBy default the plugin removes the global unique constraint on user.email so the same address can exist under different tenants. Set keepEmailGloballyUnique: true if you want one email to map to a single tenant globally.
Verify the setup
- Start your auth server
- Create a tenant via
POST /tenant/create - Sign up with
POST /tenant/sign-up/emailpassingtenantId - Confirm the session includes
tenantId
See the Next.js demo for a complete setup with PostgreSQL and Drizzle.