1---
2title: Upgrading from 1.6 to 1.7.5 or newer
3description: Upgrade Better Auth directly from 1.6, preserve existing users, and update your schema and application APIs.
4sidebar:
5 order: 3
6---
7
8Upgrade directly to 1.7.5 or a later compatible 1.x release. The core account
9schema is unchanged from 1.6; no issuer column or identity backfill is needed.
10
11:::caution[Already upgraded to 1.7.0–1.7.2?]
12Follow the [upstream issuer cleanup instructions](https://better-auth.com/docs/guides/1-7-upgrade-guide#account-identity-keeps-the-provider-key) first.
13:::
14
15## Back up existing data
16
17Back up the database and rehearse on a copy with existing users, accounts, and sessions. **Keep the same auth secret.**
18
19Resolve duplicate provider/account ID pairs using your configured table names. Never merge users by email alone.
20
21These integrations need manual preparation. Follow the corresponding
22[upstream instructions](https://better-auth.com/docs/guides/1-7-upgrade-guide):
23
24| Integration | Before deploying |
25| --- | --- |
26| Microsoft / Entra | Pause sign-in and linking; map old subject IDs to verified object IDs or a trusted directory export. |
27| Custom OAuth / SSO | Map existing subjects to verified immutable provider IDs. |
28| Legacy OIDC / MCP | Convert client registrations and legacy token tables. Schema migrations do not copy these records. |
29| SCIM | Stop old provisioning and follow the reprovisioning procedure. D1 cannot support the new transaction requirements. |
30| Device Authorization | Resolve duplicate device/user codes; use bounded strings on MySQL and SQL Server. |
31
32:::caution[Deployment does not pause existing traffic]
33Alchemy delays the new host deployment, but old instances keep running; use a maintenance window for incompatible changes. An application rollback does not reverse database changes.
34:::
35
36## Upgrade packages together
37
38Update the Alchemy Better Auth package to a release supporting 1.7.5, then
39align Better Auth and its synchronized plugins/adapters:
40
41```sh
42npx auth@1.7.5 upgrade
43```
44
45Use Node.js 22.12 or newer and the CLI version matching your target release. Review workspace catalogs and overrides.
46
47The command updates dependencies, not application code or identity data.
48
49## Apply the schema
50
51For [SQL layers with automatic migrations](/better-auth/guides/migrations#choose-the-migration-transport),
52the wrapper stays unchanged:
53
54```typescript
55import { BetterAuth } from "@alchemy.run/better-auth";
56
57export const makeAuth = BetterAuth({
58 emailAndPassword: { enabled: true },
59});
60```
61
62After any manual preparation, deploy:
63
64```sh
65alchemy deploy
66```
67
68The schema is applied before the new host. Ordinary email/password accounts
69need no identity conversion when upgrading directly from 1.6.
70
71## Generate a Drizzle schema
72
73Drizzle users own schema migrations. Generate and review the auth schema:
74
75```sh
76npx auth@1.7.5 generate --config ./auth.cli.ts
77```
78
79The CLI configuration exports an upstream Better Auth instance with the same
80plugins and schema options, using the Relations v2 adapter:
81
82```typescript
83import { drizzleAdapter } from "@better-auth/drizzle-adapter/relations-v2";
84```
85
86Omit the adapter CLI flag, which selects the legacy generator:
87
88```diff
89- npx auth@1.7.5 generate --config ./auth.cli.ts --adapter drizzle
90+ npx auth@1.7.5 generate --config ./auth.cli.ts
91```
92
93Apply the schema through Drizzle's migration tooling and include the generated auth relations when constructing the database. See the complete [Drizzle configuration](/better-auth/databases/drizzle).
94
95With automatic migrations disabled, apply your schema before deploying too.
96
97## Update application APIs
98
99Generic OAuth now uses the social APIs:
100
101```typescript
102import { createAuthClient } from "better-auth/client";
103import { genericOAuthClient } from "better-auth/client/plugins";
104
105const authClient = createAuthClient({ plugins: [genericOAuthClient()] });
106authClient.signIn.social({ provider: "my-provider" });
107authClient.linkSocial({ provider: "my-provider" });
108```
109
110Update registered callback URLs:
111
112```diff
113- /api/auth/oauth2/callback/:id
114+ /api/auth/callback/:id
115```
116
117Token/profile operations select a **local account row**, rather than a provider:
118
119```typescript
120{ accountId: "local-account-row-id" }
121// Or select the account from its cookie:
122{ useAccountCookie: true }
123```
124
125Move joins into the database options:
126
127```diff
128- experimental: { joins: true }
129+ advanced: { database: { joins: true } }
130```
131
132Custom secondary storage needs atomic operations:
133
134```typescript
135increment(key, ttl)
136getAndDelete(key)
137```
138
139The TTL is required, in seconds; subsequent increments must preserve the original expiration. Custom rate-limit storage now uses an atomic consume operation instead of separate reads and writes.
140
141Check the upstream guide for SSO, MCP, mobile, and proxy changes.
142
143## Verify existing users
144
145Test an existing session, existing-user sign-in, new-user sign-up, and sign-out. Exercise every configured provider and account link/list/refresh/unlink flow.
146
147Confirm user IDs are preserved and no duplicate users appear.
148
149Deploy again to confirm the migration is a no-op:
150
151```sh
152alchemy deploy
153```