diff --git a/docs/content/docs/concepts/database.mdx b/docs/content/docs/concepts/database.mdx
index 25f111cd6e..91791110d5 100644
--- a/docs/content/docs/concepts/database.mdx
+++ b/docs/content/docs/concepts/database.mdx
@@ -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**
+
+ **Note**: For auto-incrementing numeric IDs (serial, auto_increment), use `useNumberId: true` instead (see the Numeric IDs section below).
+
+
+#### 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();
+ },
+ },
+ },
+});
+```
+
+
+ **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.
+
+
+#### 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.
+### 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`.
+
+
+ **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.
+
+
+**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
+
+
+ **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.
+
### 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`.