using better-auth client breaks typescript server #742

Closed
opened 2026-03-13 08:02:22 -05:00 by GiteaMirror · 24 comments
Owner

Originally created by @darklight9811 on GitHub (Feb 25, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

please ignore the music, I didnt notice when I was recording it

https://github.com/user-attachments/assets/d1813ca0-3cae-485d-ad1d-8673a3843178

Current vs. Expected behavior

expected

  • the typescript server to continue working

current

  • the entire typescript server stops working for any file

What version of Better Auth are you using?

1.1.21

Provide environment information

- OS: Windows 11
- Code editor: VSCode

Which area(s) are affected? (Select all that apply)

Types

Auth config (if applicable)

import { anonymousClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/client";

export const authClient = createAuthClient({
	baseURL: `http://localhost:3000/auth`,
	plugins: [anonymousClient()],
	fetchOptions: {
		auth: {
			type: "Bearer",
			token: () => (typeof localStorage !== "undefined" ? localStorage.getItem("token") : ""),
		},
	},
});

Additional context

I noticed somewhere a stack overflow complain by typescript in one of my tests, sadly I couldnt reproduce, it was complaining about the login type excessively deep nest instantiation.

Originally created by @darklight9811 on GitHub (Feb 25, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce > please ignore the music, I didnt notice when I was recording it https://github.com/user-attachments/assets/d1813ca0-3cae-485d-ad1d-8673a3843178 ### Current vs. Expected behavior # expected - the typescript server to continue working # current - the entire typescript server stops working for any file ### What version of Better Auth are you using? 1.1.21 ### Provide environment information ```bash - OS: Windows 11 - Code editor: VSCode ``` ### Which area(s) are affected? (Select all that apply) Types ### Auth config (if applicable) ```typescript import { anonymousClient } from "better-auth/client/plugins"; import { createAuthClient } from "better-auth/client"; export const authClient = createAuthClient({ baseURL: `http://localhost:3000/auth`, plugins: [anonymousClient()], fetchOptions: { auth: { type: "Bearer", token: () => (typeof localStorage !== "undefined" ? localStorage.getItem("token") : ""), }, }, }); ``` ### Additional context I noticed somewhere a stack overflow complain by typescript in one of my tests, sadly I couldnt reproduce, it was complaining about the login type excessively deep nest instantiation.
GiteaMirror added the bug label 2026-03-13 08:02:22 -05:00
Author
Owner

@darklight9811 commented on GitHub (Feb 25, 2025):

Typescript has 8gb available of ram to use. If I try to run tsc or tsup(esbuild), the build fails because of lack of available memory.

I use a monorepo

@darklight9811 commented on GitHub (Feb 25, 2025): Typescript has 8gb available of ram to use. If I try to run tsc or tsup(esbuild), the build fails because of lack of available memory. I use a monorepo
Author
Owner

@Bekacru commented on GitHub (Feb 25, 2025):

  • make sure strict:true is set in your tsconfig
  • try setting declaration:false in your tsconfig
  • upgrade to 1.2 beta better-auth@1.2-beta.16
@Bekacru commented on GitHub (Feb 25, 2025): - make sure `strict:true` is set in your tsconfig - try setting `declaration:false` in your tsconfig - upgrade to 1.2 beta `better-auth@1.2-beta.16`
Author
Owner

@darklight9811 commented on GitHub (Feb 25, 2025):

@Bekacru only updating to better-auth@1.2-beta.16 made it work

@darklight9811 commented on GitHub (Feb 25, 2025): @Bekacru only updating to `better-auth@1.2-beta.16` made it work
Author
Owner

@ftzi commented on GitHub (Feb 25, 2025):

better-auth@1.2.0-beta.16 fixed it here as well.

@ftzi commented on GitHub (Feb 25, 2025): `better-auth@1.2.0-beta.16` fixed it here as well.
Author
Owner

@masterjanic commented on GitHub (Feb 26, 2025):

@Bekacru I can confirm this issue as well on 1.1.21. It broke my whole typescript setup and eslint stopped working as well because of that. I have literally been searching the issue everywhere else but this package...

My tsconfig.json is (and it was always working):

{
  "compilerOptions": {
    /* Base Options: */
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "es2022",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,

    /* Strictness */
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "checkJs": true,

    /* Bundled projects */
    "lib": ["dom", "dom.iterable", "ES2022"],
    "noEmit": true,
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "jsx": "preserve",
    "plugins": [{ "name": "next" }],
    "incremental": true,

    /* Path Aliases */
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": [
    ".eslintrc.cjs",
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "**/*.cjs",
    "**/*.js",
    ".next/types/**/*.ts"
  ],
  "exclude": ["node_modules"]
}
@masterjanic commented on GitHub (Feb 26, 2025): @Bekacru I can confirm this issue as well on `1.1.21`. It broke my whole typescript setup and eslint stopped working as well because of that. I have literally been searching the issue everywhere else but this package... My tsconfig.json is (and it was always working): ``` { "compilerOptions": { /* Base Options: */ "esModuleInterop": true, "skipLibCheck": true, "target": "es2022", "allowJs": true, "resolveJsonModule": true, "moduleDetection": "force", "isolatedModules": true, /* Strictness */ "strict": true, "noUncheckedIndexedAccess": true, "checkJs": true, /* Bundled projects */ "lib": ["dom", "dom.iterable", "ES2022"], "noEmit": true, "module": "ESNext", "moduleResolution": "Bundler", "jsx": "preserve", "plugins": [{ "name": "next" }], "incremental": true, /* Path Aliases */ "baseUrl": ".", "paths": { "@/*": ["./src/*"] } }, "include": [ ".eslintrc.cjs", "next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.js", ".next/types/**/*.ts" ], "exclude": ["node_modules"] } ```
Author
Owner

@ezShroom commented on GitHub (Mar 1, 2025):

+1 to this. vscode has been very slow in this project in the past, errors seemingly at random to do with infinite type instantiation, and running bun i better-auth@1.2.0-beta.18 has solved everything. @Bekacru out of interest what's causing this in 1.1x?

@ezShroom commented on GitHub (Mar 1, 2025): +1 to this. vscode has been very slow in this project in the past, errors seemingly at random to do with infinite type instantiation, and running `bun i better-auth@1.2.0-beta.18` has solved everything. @Bekacru out of interest what's causing this in 1.1x?
Author
Owner

@kien-ngo commented on GitHub (Mar 5, 2025):

Just wanna chime in here. I also have the Type instantiation is excessively deep and possibly infinite.ts(2589) error with hookform/resolvers on better-auth@1.2.3 and Vscode is incredibly slow.

The problem did not go away when I installed better-auth@1.2.0-beta.16 OR better-auth@1.2.0-beta.18

@kien-ngo commented on GitHub (Mar 5, 2025): Just wanna chime in here. I also have the `Type instantiation is excessively deep and possibly infinite.ts(2589)` error with hookform/resolvers on better-auth@1.2.3 and Vscode is incredibly slow. The problem did not go away when I installed `better-auth@1.2.0-beta.16` OR `better-auth@1.2.0-beta.18`
Author
Owner

@MendyLanda commented on GitHub (Apr 2, 2025):

+1, since adding better auth TS performance got unbearable. M4 Pro with 48GB Ram...

@MendyLanda commented on GitHub (Apr 2, 2025): +1, since adding better auth TS performance got unbearable. M4 Pro with 48GB Ram...
Author
Owner

@b3nab commented on GitHub (Apr 21, 2025):

@MendyLanda I have a M1 Max with 64GB Ram and when I open a project with better-auth it's the first time in my life I ear the fan..

I think the issue is not just for the client but both server and client (so both betterAuthand betterAuthClient) have issues probably relying too much on type inference (?).

@b3nab commented on GitHub (Apr 21, 2025): @MendyLanda I have a M1 Max with 64GB Ram and when I open a project with better-auth it's the first time in my life I ear the fan.. I think the issue is not just for the client but both server and client (so both `betterAuth`and `betterAuthClient`) have issues probably relying too much on type inference (?).
Author
Owner

@MendyLanda commented on GitHub (Apr 21, 2025):

probably relying too much on type inference (?).

That and heavy Zod usage leads to very complicated type bundles.

What I can't figure out is why so few people complain about this.. makes me doubt how I use better-auth but I can't see anything I'm doing wrong.

For comparison, I'm experiencing this on a simple side project, while my work repo that has massive trpc & drizzle schemas is so much quicker 🤷‍♂️

@MendyLanda commented on GitHub (Apr 21, 2025): > probably relying too much on type inference (?). That and heavy Zod usage leads to very complicated type bundles. What I can't figure out is why so few people complain about this.. makes me doubt how I use better-auth but I can't see anything I'm doing wrong. For comparison, I'm experiencing this on a simple side project, while my work repo that has massive trpc & drizzle schemas is so much quicker 🤷‍♂️
Author
Owner

@darklight9811 commented on GitHub (Apr 22, 2025):

@MendyLanda I saw some time back arktype discussing an improvement that could be done on typescript itself, that should help. Besides I hope the typescript port to go comes as fast as it can.

@darklight9811 commented on GitHub (Apr 22, 2025): @MendyLanda I saw some time back arktype discussing an improvement that could be done on typescript itself, that should help. Besides I hope the typescript port to go comes as fast as it can.
Author
Owner

@MendyLanda commented on GitHub (Apr 23, 2025):

@MendyLanda I saw some time back arktype discussing an improvement that could be done on typescript itself, that should help. Besides I hope the typescript port to go comes as fast as it can.

Are you referring to this? it's possible that this or the go port will help num this problem, but it will still exists, this type of library should work fine even without it as opposed to trpc/zod etc that truly needs it

@MendyLanda commented on GitHub (Apr 23, 2025): > [@MendyLanda](https://github.com/MendyLanda) I saw some time back arktype discussing an improvement that could be done on typescript itself, that should help. Besides I hope the typescript port to go comes as fast as it can. Are you referring to [this](https://github.com/microsoft/TypeScript/pull/61505)? it's possible that this or the go port will help num this problem, but it will still exists, this type of library should work fine even without it as opposed to trpc/zod etc that truly needs it
Author
Owner

@Bekacru commented on GitHub (Apr 23, 2025):

@MendyLanda could you send me your tsconfig and auth config?

We did a lot of improvements for 1.2 and we're doing a lot more soon for 1.3 release and zod v4 should help

@Bekacru commented on GitHub (Apr 23, 2025): @MendyLanda could you send me your tsconfig and auth config? We did a lot of improvements for 1.2 and we're doing a lot more soon for 1.3 release and zod v4 should help
Author
Owner

@Bekacru commented on GitHub (Apr 23, 2025):

@b3nab would be interested to see your tsconfig and auth config as well :))

@Bekacru commented on GitHub (Apr 23, 2025): @b3nab would be interested to see your tsconfig and auth config as well :))
Author
Owner

@MendyLanda commented on GitHub (Apr 23, 2025):

@Bekacru I tried investigating the issue but I couldn't replicate it...

https://github.com/MendyLanda/better-auth-ts-perf
the complex-auth.ts is my config, the tsconfig.json is identical

I commented out some irrelevant code that relied on private stuff, other than that and with the auth-react-client.ts file, everything is identical to my setup.

I'd be happy to hop on a call to show you my private repo, if that's something you want to do

@MendyLanda commented on GitHub (Apr 23, 2025): @Bekacru I tried investigating the issue but I couldn't replicate it... https://github.com/MendyLanda/better-auth-ts-perf the `complex-auth.ts` is my config, the `tsconfig.json` is identical I commented out some irrelevant code that relied on private stuff, other than that and with the `auth-react-client.ts` file, everything is identical to my setup. I'd be happy to hop on a call to show you my private repo, if that's something you want to do
Author
Owner

@MendyLanda commented on GitHub (Apr 23, 2025):

We did a lot of improvements for 1.2 and we're doing a lot more soon for 1.3 release and zod v4 should help

Based on number of instantiations, I can definitely see the improvement between 1.2.5 and 1.2.7 (see this readme)

@MendyLanda commented on GitHub (Apr 23, 2025): > We did a lot of improvements for 1.2 and we're doing a lot more soon for 1.3 release and zod v4 should help Based on number of instantiations, I can definitely see the improvement between 1.2.5 and 1.2.7 (see [this readme](https://github.com/MendyLanda/better-auth-ts-perf/blob/main/README.md))
Author
Owner

@darklight9811 commented on GitHub (Apr 23, 2025):

@MendyLanda don't forget that VSCode also limits the memory usage for the typescript server, you need to manually allow more memory

@darklight9811 commented on GitHub (Apr 23, 2025): @MendyLanda don't forget that VSCode also limits the memory usage for the typescript server, you need to manually allow more memory
Author
Owner

@MendyLanda commented on GitHub (Apr 23, 2025):

@MendyLanda don't forget that VSCode also limits the memory usage for the typescript server, you need to manually allow more memory

Thanks for the suggestion!
I've set it to 12GB but still getting stuck after a short while.

https://github.com/user-attachments/assets/e1b3fb5c-bb79-47b8-b174-8d9705b97211

@MendyLanda commented on GitHub (Apr 23, 2025): > [@MendyLanda](https://github.com/MendyLanda) don't forget that VSCode also limits the memory usage for the typescript server, you need to manually allow more memory Thanks for the suggestion! I've set it to 12GB but still getting stuck after a short while. https://github.com/user-attachments/assets/e1b3fb5c-bb79-47b8-b174-8d9705b97211
Author
Owner

@darklight9811 commented on GitHub (Apr 23, 2025):

@MendyLanda so the issue is on specific types, I know its kinda of a shore, but could you see which types are having those issues?

@darklight9811 commented on GitHub (Apr 23, 2025): @MendyLanda so the issue is on specific types, I know its kinda of a shore, but could you see which types are having those issues?
Author
Owner

@Bekacru commented on GitHub (Apr 23, 2025):

@MendyLanda this is crazy slow. I personally work on 16 gb ram m1 pro. And never even gets close to that. And I run and maintain the whole codebase :)) I'm suspecting something is not properly configured. Most likely tsconfig. I'll take a look at your POC repo. If there is more info, you can share me please do so. If it's still the case open to have a chat over a call.

@Bekacru commented on GitHub (Apr 23, 2025): @MendyLanda this is crazy slow. I personally work on 16 gb ram m1 pro. And never even gets close to that. And I run and maintain the whole codebase :)) I'm suspecting something is not properly configured. Most likely tsconfig. I'll take a look at your POC repo. If there is more info, you can share me please do so. If it's still the case open to have a chat over a call.
Author
Owner

@b3nab commented on GitHub (Apr 23, 2025):

@b3nab would be interested to see your tsconfig and auth config as well :))

I think my case is a little bit more complex than just using better-auth into my project.

I'm developing a plugin for PayloadCMS to replace their auth system with better-auth @b3nab/payload-better-auth.

Other the fact that it's a bit slow and sometimes I need to restart the TS server, I'm having trouble with properly inferred types.

@b3nab commented on GitHub (Apr 23, 2025): > [@b3nab](https://github.com/b3nab) would be interested to see your tsconfig and auth config as well :)) I think my case is a little bit more complex than just using better-auth into my project. I'm developing a plugin for PayloadCMS to replace their auth system with better-auth [@b3nab/payload-better-auth](https://github.com/b3nab/payload-better-auth). Other the fact that it's a bit slow and sometimes I need to restart the TS server, I'm having trouble with properly inferred types.
Author
Owner

@MendyLanda commented on GitHub (Apr 23, 2025):

@Bekacru

@MendyLanda so the issue is on specific types, I know its kinda of a shore, but could you see which types are having those issues?

I think it's only happening when I use one of the organization plugin endpoints.

To be clear, at least for me, this is a non-blocking issue, as it only happens when I interact with the better auth client, which is not very often. the rest of my project is not affected.

@MendyLanda commented on GitHub (Apr 23, 2025): @Bekacru > [@MendyLanda](https://github.com/MendyLanda) so the issue is on specific types, I know its kinda of a shore, but could you see which types are having those issues? I think it's only happening when I use one of the organization plugin endpoints. To be clear, at least for me, this is a non-blocking issue, as it only happens when I interact with the better auth client, which is not very often. the rest of my project is not affected.
Author
Owner

@darklight9811 commented on GitHub (May 14, 2025):

@MendyLanda started to notice this with any client api usage

@darklight9811 commented on GitHub (May 14, 2025): @MendyLanda started to notice this with any client api usage
Author
Owner

@MendyLanda commented on GitHub (Jul 30, 2025):

I spent a few hours debugging because I couldn't stand it anymore. here are my findings.

  1. Drizzle Adapter
    When you have a large drizzle database, and you pass it directly to the config, it causes a huge performance hit. You can avoid this by simply extracting the adapter outside of the config like this:

    const adapter = drizzleAdapter(db, { provider: "pg" });
    
    export const auth = betterAuth({
      database: adapter,
      // ...
    })
    

    With this alone, you might see a huge improvement! @Bekacru I would go as far to say this needs to be the recommended use of the drizzle adapter.

  2. Inline config functions / hooks
    This might not apply to all functions, but if your function uses any large type and you declare the function inline in the config, the config type increases with all that potential type complexity. To solve this, extract the functions outside of the config, and annotate it's type (important!).

    Example:

    // Do this 
    export const getTrustedOrigins: BetterAuthOptions["trustedOrigins"] = async () => {
        const tenants = await db...
        return [...];
    };
    
    export const auth = betterAuth({
      trustedOrigins: getTrustedOrigins,
    });
    
    //-----------
    
    // Not this
    export const auth = betterAuth({
      trustedOrigins: async () => {
        const tenants = await db...
        return [...];
      },
    })
    
  3. Plugins that consumes complex types.
    This is similar to point # 2, but more nuanced since you cannot simply annotate the function like I showed earlier, but the concept remains the same - and here's an example. If you need to call your db (an 'expensive' type) inside a plugin config, you can create an annotated function outside that calls the db and returns the data, and call it instead.

Important note!
The extracted function must be explicitly annotated otherwise it will have no effect. see example below.

// Good extraction annotates the function output,
// this way internal types will not effect performance. 
const getMemberForSession = async ({
  organizationId,
  userId,
}: {
  organizationId: string;
  userId: string;
}): Promise<Member | undefined> => {
  const member = await db...
  return member;
};

// -------

// Bad extraction, missing annotation
const getMemberForSession = async ({
  organizationId,
  userId,
}: {
  organizationId: string;
  userId: string;
}) => {
  const member = await db...
  return member;
};

Other findings:

  • Additional fields have little effect on performance (tested user, session & accounts)
  • Organization plugin adds about 2k instantiations, for me resulted in 15.78% bigger type.
  • Custom Session plugin adds about 1.5k instantiations, resulting (for me) in 11.81% bigger type.
  • Social providers, first one increases instantiations by 700 (4.87%), every additional one is another 100 instantiations (0.65%)
  • emailAndPassword and secondaryStorage options has no effect on performance.
@MendyLanda commented on GitHub (Jul 30, 2025): I spent a few hours debugging because I couldn't stand it anymore. here are my findings. 1. Drizzle Adapter When you have a large drizzle database, and you pass it directly to the config, it causes a huge performance hit. You can avoid this by simply extracting the adapter outside of the config like this: ```ts const adapter = drizzleAdapter(db, { provider: "pg" }); export const auth = betterAuth({ database: adapter, // ... }) ``` With this alone, you might see a **huge** improvement! @Bekacru I would go as far to say this needs to be the recommended use of the drizzle adapter. 2. Inline config functions / hooks This might not apply to all functions, but if your function uses any large type and you declare the function inline in the config, the config type increases with all that potential type complexity. To solve this, extract the functions outside of the config, and annotate it's type (important!). Example: ```ts // Do this export const getTrustedOrigins: BetterAuthOptions["trustedOrigins"] = async () => { const tenants = await db... return [...]; }; export const auth = betterAuth({ trustedOrigins: getTrustedOrigins, }); //----------- // Not this export const auth = betterAuth({ trustedOrigins: async () => { const tenants = await db... return [...]; }, }) ``` 3. Plugins that consumes complex types. This is similar to point # 2, but more nuanced since you cannot simply annotate the function like I showed earlier, but the concept remains the same - and here's an example. If you need to call your db (an 'expensive' type) inside a plugin config, you can create an annotated function outside that calls the db and returns the data, and call it instead. Important note! The extracted function must be explicitly annotated otherwise it will have no effect. see example below. ```ts // Good extraction annotates the function output, // this way internal types will not effect performance. const getMemberForSession = async ({ organizationId, userId, }: { organizationId: string; userId: string; }): Promise<Member | undefined> => { const member = await db... return member; }; // ------- // Bad extraction, missing annotation const getMemberForSession = async ({ organizationId, userId, }: { organizationId: string; userId: string; }) => { const member = await db... return member; }; ``` Other findings: - Additional fields have little effect on performance (tested user, session & accounts) - Organization plugin adds about 2k instantiations, for me resulted in 15.78% bigger type. - Custom Session plugin adds about 1.5k instantiations, resulting (for me) in 11.81% bigger type. - Social providers, first one increases instantiations by 700 (4.87%), every additional one is another 100 instantiations (0.65%) - emailAndPassword and secondaryStorage options has no effect on performance.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#742