[GH-ISSUE #1752] cookieCache not working #8899

Closed
opened 2026-04-13 04:08:50 -05:00 by GiteaMirror · 18 comments
Owner

Originally created by @LaurinBrechter on GitHub (Mar 9, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/1752

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

I just migrated from next-auth to better-auth on a nextjs project. I am using the auth.ts configuration below and then I get the session like so

const data = await auth.api.getSession({
    headers: await headers(),
  });

Current vs. Expected behavior

When I look into the logs of drizzle, however, my database still gets queried each time getSession gets called. I expected the database to not get queried after the initial call to getSession (or when maxAge is exceeded)

What version of Better Auth are you using?

1.2.3

Provide environment information

- ubuntu
- chrome version 131.0.6778.204
- nextjs canary version
- drizzle: 0.38.3

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

Backend

Auth config (if applicable)

import { db } from "../db";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { betterAuth } from "better-auth";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
  }),
  session: {
    cookieCache: {
      enabled: true,
      maxAge: 5 * 60, // Cache duration in seconds
    },
  },
  socialProviders: {
    github: {
      clientId: process.env.GITHUB_CLIENT_ID as string,
      clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
    },
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
  },
});

Additional context

No response

Originally created by @LaurinBrechter on GitHub (Mar 9, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/1752 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce I just migrated from next-auth to better-auth on a nextjs project. I am using the auth.ts configuration below and then I get the session like so ```javascript const data = await auth.api.getSession({ headers: await headers(), }); ``` ### Current vs. Expected behavior When I look into the logs of drizzle, however, my database still gets queried each time getSession gets called. I expected the database to not get queried after the initial call to getSession (or when maxAge is exceeded) ### What version of Better Auth are you using? 1.2.3 ### Provide environment information ```bash - ubuntu - chrome version 131.0.6778.204 - nextjs canary version - drizzle: 0.38.3 ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { db } from "../db"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { betterAuth } from "better-auth"; export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg", }), session: { cookieCache: { enabled: true, maxAge: 5 * 60, // Cache duration in seconds }, }, socialProviders: { github: { clientId: process.env.GITHUB_CLIENT_ID as string, clientSecret: process.env.GITHUB_CLIENT_SECRET as string, }, google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, }, }); ``` ### Additional context _No response_
GiteaMirror added the lockedbug labels 2026-04-13 04:08:50 -05:00
Author
Owner

@aow3xm commented on GitHub (Mar 12, 2025):

do you have a solution yet?

<!-- gh-comment-id:2717585142 --> @aow3xm commented on GitHub (Mar 12, 2025): do you have a solution yet?
Author
Owner

@LaurinBrechter commented on GitHub (Mar 12, 2025):

No, not yet.

<!-- gh-comment-id:2718355405 --> @LaurinBrechter commented on GitHub (Mar 12, 2025): No, not yet.
Author
Owner

@hbmartin commented on GitHub (Mar 18, 2025):

This does seem like a bug given the docs, but isn't this preferable from a security perspective? Cookies are as untrustworthy as any other client sent data.

<!-- gh-comment-id:2731513283 --> @hbmartin commented on GitHub (Mar 18, 2025): This does seem like a bug given the docs, but isn't this preferable from a security perspective? Cookies are as untrustworthy as any other client sent data.
Author
Owner

@moshetanzer commented on GitHub (Mar 23, 2025):

Hey,

Happy to look into this, do you mind providing a simple reproduction?

<!-- gh-comment-id:2746351418 --> @moshetanzer commented on GitHub (Mar 23, 2025): Hey, Happy to look into this, do you mind providing a simple reproduction?
Author
Owner

@LaurinBrechter commented on GitHub (Mar 24, 2025):

Hey, yes I can try making a simple example. I'll post the link to the GH repo when I have it.

<!-- gh-comment-id:2747116148 --> @LaurinBrechter commented on GitHub (Mar 24, 2025): Hey, yes I can try making a simple example. I'll post the link to the GH repo when I have it.
Author
Owner

@LaurinBrechter commented on GitHub (Mar 30, 2025):

@moshetanzer Hey, I have looked into this again and also tried redis as the secondary storage. Essentially I am just using the code from the example docs:

secondaryStorage: {
    get: async (key) => {
      const value = await redis.get(key);
      return value ? JSON.stringify(value) : null;
    },
    set: async (key, value, ttl) => {
      console.log("setting", key, value, ttl);
      if (ttl) await redis.set(key, value, { EX: ttl });
      // or for ioredis:
      // if (ttl) await redis.set(key, value, 'EX', ttl)
      else await redis.set(key, value);
    },
    delete: async (key) => {
      await redis.del(key);
    },
  },

But when I then use it:

const data = await auth.api.getSession({
    headers: await headers(),
  });

I get the following error:
INTERNAL_SERVER_ERROR TypeError: Cannot read properties of undefined (reading 'expiresAt')

I checked what is returned by redis:

{"user":{"id":"<>","name":"<>","email":"<>","emailVerified":false,"image":"","createdAt":"2025-03-13T07:35:19.139Z","updatedAt":"2025-03-13T07:35:19.139Z"},"session":{"ipAddress":"127.0.0.1","userAgent":"<>","expiresAt":"2025-04-06T08:12:52.703Z","userId":"<>","token":"<>","createdAt":"2025-03-30T08:12:52.704Z","updatedAt":"2025-03-30T08:12:52.704Z"}}

When I define the secondary storage, can better auth use my primary db as a fallback?

<!-- gh-comment-id:2764462580 --> @LaurinBrechter commented on GitHub (Mar 30, 2025): @moshetanzer Hey, I have looked into this again and also tried redis as the secondary storage. Essentially I am just using the code from the example docs: ```javascript secondaryStorage: { get: async (key) => { const value = await redis.get(key); return value ? JSON.stringify(value) : null; }, set: async (key, value, ttl) => { console.log("setting", key, value, ttl); if (ttl) await redis.set(key, value, { EX: ttl }); // or for ioredis: // if (ttl) await redis.set(key, value, 'EX', ttl) else await redis.set(key, value); }, delete: async (key) => { await redis.del(key); }, }, ``` But when I then use it: ```javascript const data = await auth.api.getSession({ headers: await headers(), }); ``` I get the following error: `INTERNAL_SERVER_ERROR TypeError: Cannot read properties of undefined (reading 'expiresAt')` I checked what is returned by redis: ``` {"user":{"id":"<>","name":"<>","email":"<>","emailVerified":false,"image":"","createdAt":"2025-03-13T07:35:19.139Z","updatedAt":"2025-03-13T07:35:19.139Z"},"session":{"ipAddress":"127.0.0.1","userAgent":"<>","expiresAt":"2025-04-06T08:12:52.703Z","userId":"<>","token":"<>","createdAt":"2025-03-30T08:12:52.704Z","updatedAt":"2025-03-30T08:12:52.704Z"}} ``` When I define the secondary storage, can better auth use my primary db as a fallback?
Author
Owner

@Kinfe123 commented on GitHub (May 1, 2025):

@LaurinBrechter is this still actually an issue ?

<!-- gh-comment-id:2845864069 --> @Kinfe123 commented on GitHub (May 1, 2025): @LaurinBrechter is this still actually an issue ?
Author
Owner

@LaurinBrechter commented on GitHub (May 2, 2025):

Probably yes, I have now just solved it myself by wrapping auth.api.getSession in a function that takes care of caching. The function reads the session token from the cookies. Then checks if it exists in redis. If it does, the user is autd'd if not, we look in the db. If we find it in the db the user is also authenticated and we create the cache entry in redis with the appropriate expiresAt.

<!-- gh-comment-id:2846433278 --> @LaurinBrechter commented on GitHub (May 2, 2025): Probably yes, I have now just solved it myself by wrapping `auth.api.getSession` in a function that takes care of caching. The function reads the session token from the cookies. Then checks if it exists in redis. If it does, the user is autd'd if not, we look in the db. If we find it in the db the user is also authenticated and we create the cache entry in redis with the appropriate expiresAt.
Author
Owner

@Benjamin-Lee commented on GitHub (Jun 2, 2025):

Yes this is still an issue. Can confirm it as of 1.2.8. Happy to jump on a call to demo

<!-- gh-comment-id:2932668063 --> @Benjamin-Lee commented on GitHub (Jun 2, 2025): Yes this is still an issue. Can confirm it as of 1.2.8. Happy to jump on a call to demo
Author
Owner

@Bekacru commented on GitHub (Jun 7, 2025):

My guess is auth.api.getSession wasn't able to set cookies cause it's only called in a server component context.
Make sure

  • Next Cookies plugin is mounted
  • You're calling getSession from the client/middleware/server action regularly so it'll be able to set cookies
<!-- gh-comment-id:2951409441 --> @Bekacru commented on GitHub (Jun 7, 2025): My guess is auth.api.getSession wasn't able to set cookies cause it's only called in a server component context. Make sure - Next Cookies plugin is mounted - You're calling getSession from the client/middleware/server action regularly so it'll be able to set cookies
Author
Owner

@miguelrk commented on GitHub (Jun 10, 2025):

Is this solved with the new getSessionCookie() helper released in 1.2.9? I am also experiencing this in a NUXT middleware (not Next.js), where calling useFetch() in a route middleware will not read from the cookie cache, but make a server request on each navigation.

<!-- gh-comment-id:2958390860 --> @miguelrk commented on GitHub (Jun 10, 2025): Is this solved with the new [`getSessionCookie()` helper](https://www.better-auth.com/docs/integrations/next#middleware) released in `1.2.9`? I am also experiencing this in a NUXT middleware (not Next.js), where calling `useFetch()` in a route middleware will not read from the cookie cache, but make a server request on each navigation.
Author
Owner

@Mateleo commented on GitHub (Jun 20, 2025):

I have the same issue in Nuxt @miguelrk. Did you find a solution ?

<!-- gh-comment-id:2991325329 --> @Mateleo commented on GitHub (Jun 20, 2025): I have the same issue in Nuxt @miguelrk. Did you find a solution ?
Author
Owner

@miguelrk commented on GitHub (Jun 20, 2025):

I have the same issue in Nuxt @miguelrk. Did you find a solution ?

Unfortunately no, an API request is still being made each time I try to get the session despite the session.cookieCache configuration.

I hope the team can look at this soon.

<!-- gh-comment-id:2992354288 --> @miguelrk commented on GitHub (Jun 20, 2025): > I have the same issue in Nuxt [@miguelrk](https://github.com/miguelrk). Did you find a solution ? Unfortunately no, an API request is still being made each time I try to get the session despite the `session.cookieCache` configuration. I hope the team can look at this soon.
Author
Owner

@maccman commented on GitHub (Jun 22, 2025):

I'm also seeing this with Astro.

<!-- gh-comment-id:2994298834 --> @maccman commented on GitHub (Jun 22, 2025): I'm also seeing this with Astro.
Author
Owner

@dannylin108 commented on GitHub (Jul 6, 2025):

I'm also seeing this with Astro.

For Astro:

If session is requested from client, for example SolidJS' :

const authClient = createAuthClient({
    plugins: [
       // ...
    ]
});

const session = await authClient.getSession();

it will re-create session_data cookie, if it expired (after 5 minutes by default)

but if get session from Astro's middleware (as per the docs):

export const onRequest = defineMiddleware(async (context, next) => {
    const isAuthed = await auth.api
        .getSession({
            headers: context.request.headers,
        })
 
    if (isAuthed) {
        context.locals.user = isAuthed.user;
        context.locals.session = isAuthed.session;
    } else {
        context.locals.user = null;
        context.locals.session = null;
    }
 
    return next();
});

it WILL use session_data cookie without triggering DB, but NOT RE-CREATE it if it's expired (as it works, for example, for TanStack start)

<!-- gh-comment-id:3041172746 --> @dannylin108 commented on GitHub (Jul 6, 2025): > I'm also seeing this with Astro. For Astro: If session is requested from client, for example SolidJS' : ```TS const authClient = createAuthClient({ plugins: [ // ... ] }); const session = await authClient.getSession(); ``` it will re-create `session_data` cookie, if it expired (after 5 minutes by default) but if get session from Astro's middleware (as per the docs): ```TS export const onRequest = defineMiddleware(async (context, next) => { const isAuthed = await auth.api .getSession({ headers: context.request.headers, }) if (isAuthed) { context.locals.user = isAuthed.user; context.locals.session = isAuthed.session; } else { context.locals.user = null; context.locals.session = null; } return next(); }); ``` it WILL use `session_data` cookie without triggering DB, but NOT RE-CREATE it if it's expired (as it works, for example, for TanStack start)
Author
Owner

@miguelrk commented on GitHub (Aug 14, 2025):

Any updates on this? 🙏🏼 Doing a full network request to /get-session on each client-side is slowing down my Nuxt.js SPA notoriously in production, despite having proper session.cookeCache settings like above

<!-- gh-comment-id:3188104792 --> @miguelrk commented on GitHub (Aug 14, 2025): Any updates on this? 🙏🏼 Doing a full network request to `/get-session` on each client-side is slowing down my Nuxt.js SPA notoriously in production, despite having proper `session.cookeCache` settings like above
Author
Owner

@dannylin108 commented on GitHub (Aug 26, 2025):

@miguelrk check out this discussion https://github.com/better-auth/better-auth/discussions/4231

Doing a full network request to /get-session on each client-side

I was doing the same, but now implemented that work-around with cookies forwarding, and it works now.

<!-- gh-comment-id:3223440403 --> @dannylin108 commented on GitHub (Aug 26, 2025): @miguelrk check out this discussion https://github.com/better-auth/better-auth/discussions/4231 > Doing a full network request to `/get-session` on each client-side I was doing the same, but now implemented that work-around with cookies forwarding, and it works now.
Author
Owner

@dosubot[bot] commented on GitHub (Nov 25, 2025):

Hi, @LaurinBrechter. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary:

  • You reported that the cookieCache feature in better-auth does not prevent repeated DB queries on getSession calls in Next.js, even when enabled with a 5-minute maxAge.
  • You shared a manual Redis caching workaround to mitigate the issue.
  • Other users confirmed the problem persists in versions 1.2.8+ and across frameworks like Nuxt and Astro, causing repeated network requests and performance degradation.
  • Discussions pointed to potential causes involving server/client context and cookie handling, with some workarounds like forwarding cookies or using getSessionCookie() in 1.2.9.
  • A complete fix for this issue has not yet been implemented.

Next Steps:

  • Please let me know if this issue is still relevant with the latest version of better-auth by commenting here to keep the discussion open.
  • If I do not hear back within 7 days, I will automatically close this issue to help keep the backlog manageable.

Thank you for your understanding and contribution!

<!-- gh-comment-id:3576434760 --> @dosubot[bot] commented on GitHub (Nov 25, 2025): Hi, @LaurinBrechter. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary:** - You reported that the cookieCache feature in better-auth does not prevent repeated DB queries on getSession calls in Next.js, even when enabled with a 5-minute maxAge. - You shared a manual Redis caching workaround to mitigate the issue. - Other users confirmed the problem persists in versions 1.2.8+ and across frameworks like Nuxt and Astro, causing repeated network requests and performance degradation. - Discussions pointed to potential causes involving server/client context and cookie handling, with some workarounds like forwarding cookies or using getSessionCookie() in 1.2.9. - A complete fix for this issue has not yet been implemented. **Next Steps:** - Please let me know if this issue is still relevant with the latest version of better-auth by commenting here to keep the discussion open. - If I do not hear back within 7 days, I will automatically close this issue to help keep the backlog manageable. Thank you for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8899