mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-23 18:35:52 -05:00
docs: clarify generateId behavior and mixed ID types (#5173)
Co-authored-by: Maxwell <145994855+ping-maxwell@users.noreply.github.com>
This commit is contained in:
co-authored by
Maxwell
parent
58ffd0bc92
commit
5ebdef19c1
@@ -471,11 +471,11 @@ export const auth = betterAuth({
|
||||
|
||||
### ID Generation
|
||||
|
||||
Better Auth by default will generate unique IDs for users, sessions, and other entities. If you want to customize how IDs are generated, you can configure this in the `advanced.database.generateId` option in your auth config.
|
||||
Better Auth by default will generate unique IDs for users, sessions, and other entities. You can customize ID generation behavior using the `advanced.database.generateId` option or `advanced.database.useNumberId`.
|
||||
|
||||
You can also disable ID generation by setting the `advanced.database.generateId` option to `false`. This will assume your database will generate the ID automatically.
|
||||
#### Option 1: Let Database Generate IDs
|
||||
|
||||
**Example: Automatic Database IDs**
|
||||
Setting `generateId` to `false` disables ID generation globally, letting your database handle all ID generation:
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth";
|
||||
@@ -485,13 +485,48 @@ export const auth = betterAuth({
|
||||
database: db,
|
||||
advanced: {
|
||||
database: {
|
||||
generateId: false,
|
||||
generateId: false, // Database generates all IDs
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Example: Using a Custom ID Generator**
|
||||
<Callout type="info">
|
||||
**Note**: For auto-incrementing numeric IDs (serial, auto_increment), use `useNumberId: true` instead (see the Numeric IDs section below).
|
||||
</Callout>
|
||||
|
||||
#### Option 2: Custom ID Generation Function
|
||||
|
||||
Use a function to generate IDs. You can return `false` or `undefined` from the function to let the database generate the ID for specific models:
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth";
|
||||
import { db } from "./db";
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: db,
|
||||
advanced: {
|
||||
database: {
|
||||
generateId: (options) => {
|
||||
// Let database auto-generate for specific models
|
||||
if (options.model === "user" || options.model === "users") {
|
||||
return false; // Let database generate ID
|
||||
}
|
||||
// Generate UUIDs for other tables
|
||||
return crypto.randomUUID();
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
<Callout type="info">
|
||||
**Important**: Returning `false` or `undefined` from the `generateId` function lets the database handle ID generation for that specific model. Setting `generateId: false` (without a function) disables ID generation for **all** tables.
|
||||
</Callout>
|
||||
|
||||
#### Option 3: Consistent Custom ID Generator
|
||||
|
||||
Generate the same type of ID for all tables:
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth";
|
||||
@@ -538,6 +573,50 @@ export const auth = betterAuth({
|
||||
this is normal. It's also expected that all id values passed to Better-Auth (eg via an endpoint body) is expected to be a string.
|
||||
</Callout>
|
||||
|
||||
### Mixed ID Types
|
||||
|
||||
If you need different ID types across tables (e.g., integer IDs for users, UUID strings for sessions/accounts/verification), use a `generateId` function instead of `useNumberId`.
|
||||
|
||||
<Callout type="warn">
|
||||
**Do NOT use `useNumberId` when mixing ID types**. The `useNumberId` option is global and affects all tables. It will disable internal ID generation and expect all IDs to be numbers.
|
||||
</Callout>
|
||||
|
||||
**Example: Integer IDs for Users, UUIDs for Other Tables**
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth";
|
||||
import { db } from "./db";
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: db,
|
||||
user: {
|
||||
modelName: "users", // PostgreSQL: id serial primary key
|
||||
},
|
||||
session: {
|
||||
modelName: "session", // PostgreSQL: id text primary key
|
||||
},
|
||||
advanced: {
|
||||
database: {
|
||||
// Do NOT set useNumberId - it's global and affects all tables
|
||||
generateId: (options) => {
|
||||
if (options.model === "user" || options.model === "users") {
|
||||
return false; // Let PostgreSQL serial generate it
|
||||
}
|
||||
return crypto.randomUUID(); // UUIDs for session, account, verification
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
This configuration allows you to:
|
||||
- Use database auto-increment (serial, auto_increment, etc.) for the users table
|
||||
- Generate UUIDs for all other tables (session, account, verification)
|
||||
- Maintain compatibility with existing schemas that use different ID types
|
||||
|
||||
<Callout type="info">
|
||||
**Use Case**: This is particularly useful when migrating from other authentication providers (like Clerk) where you have existing users with integer IDs but want UUID strings for new tables.
|
||||
</Callout>
|
||||
|
||||
### Database Hooks
|
||||
|
||||
@@ -616,6 +695,7 @@ export const auth = betterAuth({
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
#### Throwing Errors
|
||||
|
||||
If you want to stop the database hook from proceeding, you can throw errors using the `APIError` class imported from `better-auth/api`.
|
||||
|
||||
Reference in New Issue
Block a user