diff --git a/.changeset/quiet-tables-check-schema.md b/.changeset/quiet-tables-check-schema.md new file mode 100644 index 0000000000..8414982e8a --- /dev/null +++ b/.changeset/quiet-tables-check-schema.md @@ -0,0 +1,10 @@ +--- +"better-auth": patch +"@better-auth/core": patch +"@better-auth/kysely-adapter": patch +"auth": patch +--- + +Report missing tables, missing columns, and required columns Better Auth never writes during initialization, with guidance for fixing them. Kysely checks the live database schema. Authentication requests await the same check and are rejected if the schema does not match. + +Validation is enabled by default, including in production. Set `advanced.database.validateSchema: false` to disable runtime validation. `auth migrate` refuses to apply changes when required unwritten columns need manual repair. diff --git a/docs/content/docs/concepts/database.mdx b/docs/content/docs/concepts/database.mdx index b3b0fd8f03..3b2dca8f23 100644 --- a/docs/content/docs/concepts/database.mdx +++ b/docs/content/docs/concepts/database.mdx @@ -123,6 +123,28 @@ await runMigrations(); +## Schema Validation + +During initialization, Better Auth compares the schema with the tables it writes and reports missing tables, missing columns, and required columns it never fills, together with their fixes. Errors appear through your configured logger without waiting for an authentication request. Requests await the same check and fail if the schema does not match; validation does not automatically stop your server or build. + +Validation is enabled by default, including in production, and caches a clean result or mismatch per adapter instance. Programmatic migrations invalidate cached checks for the same database instance. Requests waiting on an invalidated check await the new result. Restart after applying schema changes with other tools. Kysely reads live database metadata and needs database access during initialization. Custom adapters without a registered check are not validated. + +For adapters without schema validation, initialization logs a warning if you explicitly set `validateSchema: true`, or a debug message if you omit the option. Database operations proceed normally. + +Set `advanced.database.validateSchema` to `false` to disable runtime validation and its skip message. `auth migrate` and `auth generate` retain their own schema diagnostics. + +```ts title="auth.ts" +import { betterAuth } from "better-auth"; + +export const auth = betterAuth({ + advanced: { + database: { + validateSchema: false, // [!code highlight] + }, + }, +}); +``` + ## Secondary Storage Secondary storage in Better Auth allows you to use key-value stores for managing session data, verification records, rate limiting counters, and other short-lived auth data. This can be useful when you want to offload the storage of intensive records to a high performance storage or even RAM. diff --git a/docs/content/docs/reference/options.mdx b/docs/content/docs/reference/options.mdx index 0f0bd5c87d..9d38369d69 100644 --- a/docs/content/docs/reference/options.mdx +++ b/docs/content/docs/reference/options.mdx @@ -648,6 +648,7 @@ export const auth = betterAuth({ })) | false | "serial" | "uuid", defaultFindManyLimit: 100, joins: false, + validateSchema: true, }, backgroundTasks: { handler: (promise) => { /* e.g. waitUntil(promise) */ } @@ -680,6 +681,7 @@ Set custom strategies for ID generation, findMany queries, and database joins. * `generateId`: Controls how record IDs are generated. Accepts a custom function, `false`, `"serial"`, or `"uuid"` (default: [random base62 string](https://github.com/better-auth/better-auth/blob/main/packages/core/src/utils/id.ts)). See the [Database documentation](/docs/concepts/database#id-generation) for more info. * `defaultFindManyLimit`: The default maximum number of records returned by the `findMany` adapter method. (default: `100`) * `joins`: Enable database joins for adapters that support them. When disabled (default), related data is fetched via separate queries. See the [Database documentation](/docs/concepts/database#joins) for more info. (default: `false`) +* `validateSchema`: Compare the schema with the tables Better Auth writes before the first request and report every difference with its fix. See the [Database documentation](/docs/concepts/database#schema-validation) for more info. (default: `true` outside production) ```ts import { betterAuth } from "better-auth"; diff --git a/packages/better-auth/src/api/index.ts b/packages/better-auth/src/api/index.ts index 89999daed9..4b3faefcab 100644 --- a/packages/better-auth/src/api/index.ts +++ b/packages/better-auth/src/api/index.ts @@ -300,6 +300,9 @@ export const router =