These models live in the Postgres auth schema and are declared only in packages/database/prisma/schema.prisma. better-auth reads and writes them through prismaAdapter(db, { provider: 'postgresql' }) in packages/auth/src/auth.ts. Table names are lowercase singular (user, session, member) because better-auth expects them that way. advanced.database.generateId is false, so ids come from the Prisma @default(cuid()), not from better-auth.
createdAt and updatedAt on most auth tables have no database default. better-auth supplies the values. If you insert rows by hand, set them yourself.
There is no foreign key between the auth and public schemas. The links are plain string columns: A staff user can belong to several organizations, so one User can map to several Coach rows, one per studio. The web lane upserts the owner’s Coach row on first request with role: 'HEAD_COACH'.

User

Table auth.user. One row per person who can sign in: studio owners, staff and trainees. Unique constraints: email, username, phoneNumber. Relations: sessions, accounts, passkeys, invitations (as inviter), purchases, members, twofactors, notifications, notificationPreferences. All cascade on user delete.

Session

Table auth.session. One row per signed-in device. Indexes: unique token, index on userId.

Account

Table auth.account. One row per sign-in method of a user. Index on userId. Account linking trusts google and github as providers (trustedProviders in auth.ts). Google is the only social provider configured under socialProviders.

Verification

Table auth.verification. Short-lived values better-auth needs to check later: magic link tokens, email OTP codes, phone OTP codes, password reset tokens.

Passkey

Table auth.passkey. WebAuthn credentials from the passkey() plugin. Indexes on userId and credentialID.

TwoFactor

Table auth.twoFactor. Perform wraps the plugin in twoFactorWithOtpLanes (packages/auth/src/plugins/two-factor-otp-lanes.ts).

Organization

Table auth.organization. One row per studio account. The domain twin is Studio. Relations: members, invitations, purchases. All cascade on organization delete. The beforeDeleteOrganization hook calls beforeOrganizationDelete (packages/auth/src/lib/deletion-hooks.ts) before the row goes.

Member

Table auth.member. Membership of a user in an organization. Unique on (organizationId, userId). Indexes on each column.

Invitation

Table auth.invitation. Pending staff invites. sendInvitationEmail sends the organizationInvitation template with a link to /login if the email already has a user, or /signup otherwise, carrying invitationId and email as query parameters. Pending invitations count toward the team seat limit. See Billing models.

Sign-in methods

The plugins enabled in auth.ts decide which rows get written: The delivery side of the OTP and email methods is covered in SmartSend WhatsApp and Email.

Coach web notifications

Two more auth models belong to the web app’s in-app notification bell. They are documented with the other notification tables in Messaging and notifications: Notification and UserNotificationPreference, with the enums NotificationType and NotificationTarget.