How to use Better Auth on Lambda #1722

Closed
opened 2026-03-13 08:58:40 -05:00 by GiteaMirror · 8 comments
Owner

Originally created by @ArifAA14 on GitHub (Aug 16, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Setup AWS Lambda with HonoJS and follow Better Auth docs
  2. Setup NextJS Project

Current vs. Expected behavior

Hey so I have a use case where my Better Auth server will be hosted on aws lamba, behind an API Gateway, I have managed to set it up and it works fine.

I have a front end which is NextJS App Router, so now when I hit my better auth server for login it works and sets a cookie temporarily but on redirect (callbackURL), the cookie disappears and in a server component

I have a few questions

  • Since I have a better auth server on lambda, do I need to recreate it within NextJS? My use case is use to utilize NextJS RSC so I kind of need the auth.api.getSession() instead of the authClient hooks.
async function LandingPage() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  console.log(session);

The above code always returns null, even after a successful, sign in, I have checked it by verifying my db and API response.

My auth.ts (In NextJS) - I don't add any DB config here cause thats handled by the auth server on Lambda.

export const auth = betterAuth({
  baseURL: `${baseURL}/api/auth`,

  advanced: {
    defaultCookieAttributes: {
      sameSite: 'none',
      secure: true,
      partitioned: true,
    },
  },
});

My auth-client.ts

export const authClient = createAuthClient({
  baseURL: `${baseURL}/api/auth`,
  credentials: true,
  plugins: [
    inferAdditionalFields<typeof auth>(),
    stripeClient({
      subscription: false,
    }),
  ],
  fetchOptions: {
    credentials: 'include',
  },
});

export const { signIn, signOut, signUp, useSession, updateUser } = authClient;

Finally my auth.ts on Lambda

export const auth = betterAuth({
  database: new Pool({
    connectionString:
      "dburl",
    max: 2,
    min: 0,
    idleTimeoutMillis: 30000,
    connectionTimeoutMillis: 10000, // 10 second connection timeout
  }),
  trustedOrigins: ["http://localhost:3000", "http://localhost:3001"],
  advanced: {
    defaultCookieAttributes: {
      sameSite: "None",
      secure: false,
      partitioned: true,
      domain: "localhost",
    },
  },
  emailAndPassword: {
    enabled: true,
    async sendResetPassword(data, request) {
      console.log(data, request);
    },
    autoSignIn: true,
  },
  },
  plugins: [
    stripe({
      stripeClient,
      stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
      createCustomerOnSignUp: true,
    }),
  ],
});

Main Issues

  • Not sure whether I need to define a better auth server in NextJS again, if I have already done so in Lambda
  • Currently when I login using the better auth server on lambda, the session cookie is only set till the redirect, once the redirect happens its gone and session is always null, even though a new session row has been added in the database.

What version of Better Auth are you using?

1.3.6

System info

Not applicable

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

Backend, Client

Originally created by @ArifAA14 on GitHub (Aug 16, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Setup AWS Lambda with HonoJS and follow Better Auth docs 2. Setup NextJS Project ### Current vs. Expected behavior Hey so I have a use case where my Better Auth server will be hosted on aws lamba, behind an API Gateway, I have managed to set it up and it works fine. I have a front end which is NextJS App Router, so now when I hit my better auth server for login it works and sets a cookie temporarily but on redirect (callbackURL), the cookie disappears and in a server component I have a few questions - Since I have a better auth server on lambda, do I need to recreate it within NextJS? My use case is use to utilize NextJS RSC so I kind of need the `auth.api.getSession()` instead of the authClient hooks. ``` async function LandingPage() { const session = await auth.api.getSession({ headers: await headers(), }); console.log(session); ``` The above code always returns null, even after a successful, sign in, I have checked it by verifying my db and API response. My auth.ts (In NextJS) - I don't add any DB config here cause thats handled by the auth server on Lambda. ``` export const auth = betterAuth({ baseURL: `${baseURL}/api/auth`, advanced: { defaultCookieAttributes: { sameSite: 'none', secure: true, partitioned: true, }, }, }); ``` My auth-client.ts ``` export const authClient = createAuthClient({ baseURL: `${baseURL}/api/auth`, credentials: true, plugins: [ inferAdditionalFields<typeof auth>(), stripeClient({ subscription: false, }), ], fetchOptions: { credentials: 'include', }, }); export const { signIn, signOut, signUp, useSession, updateUser } = authClient; ``` **Finally my auth.ts on Lambda** ``` export const auth = betterAuth({ database: new Pool({ connectionString: "dburl", max: 2, min: 0, idleTimeoutMillis: 30000, connectionTimeoutMillis: 10000, // 10 second connection timeout }), trustedOrigins: ["http://localhost:3000", "http://localhost:3001"], advanced: { defaultCookieAttributes: { sameSite: "None", secure: false, partitioned: true, domain: "localhost", }, }, emailAndPassword: { enabled: true, async sendResetPassword(data, request) { console.log(data, request); }, autoSignIn: true, }, }, plugins: [ stripe({ stripeClient, stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!, createCustomerOnSignUp: true, }), ], }); ``` Main Issues - Not sure whether I need to define a better auth server in NextJS again, if I have already done so in Lambda - Currently when I login using the better auth server on lambda, the session cookie is only set till the redirect, once the redirect happens its gone and session is always null, even though a new session row has been added in the database. ### What version of Better Auth are you using? 1.3.6 ### System info ```bash Not applicable ``` ### Which area(s) are affected? (Select all that apply) Backend, Client
GiteaMirror added the nextjshono labels 2026-03-13 08:58:40 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Aug 16, 2025):

You do not need to recreate the Better Auth server within NextJS—using the baseURL to point to your Lambda backend is the correct approach for server-side session retrieval with auth.api.getSession(). The main reason getSession() returns null is almost always due to cookies not being sent or received properly between your frontend and backend, especially in cross-origin setups like Lambda behind API Gateway and NextJS App Router.

Make sure your cookies are set with SameSite=None and Secure=true, and that your API Gateway is configured to forward Set-Cookie headers correctly. Also, verify that your frontend requests include credentials and that the domain attribute on your cookies matches your frontend domain. Recent fixes in Better Auth addressed bugs where session data from cookies was not properly added to the context, causing null sessions in hooks—so ensure you’re running the latest version and your cookie attributes are consistent across both Lambda and NextJS configs (source, source).

If the cookie disappears after redirect, use browser dev tools to inspect the Set-Cookie headers and confirm the cookie is being set and sent on subsequent requests. Double-check your API Gateway settings to ensure it isn’t stripping or blocking cookies. You do not need to run a local Better Auth instance in NextJS—just ensure cookies are correctly propagated and accessible in server-side requests (source).

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Aug 16, 2025): <!-- Answer --> You do not need to recreate the Better Auth server within NextJS—using the baseURL to point to your Lambda backend is the correct approach for server-side session retrieval with auth.api.getSession(). The main reason getSession() returns null is almost always due to cookies not being sent or received properly between your frontend and backend, especially in cross-origin setups like Lambda behind API Gateway and NextJS App Router. Make sure your cookies are set with SameSite=None and Secure=true, and that your API Gateway is configured to forward Set-Cookie headers correctly. Also, verify that your frontend requests include credentials and that the domain attribute on your cookies matches your frontend domain. Recent fixes in Better Auth addressed bugs where session data from cookies was not properly added to the context, causing null sessions in hooks—so ensure you’re running the latest version and your cookie attributes are consistent across both Lambda and NextJS configs ([source](https://github.com/better-auth/better-auth/pull/3578), [source](https://github.com/better-auth/better-auth/pull/3283)). If the cookie disappears after redirect, use browser dev tools to inspect the Set-Cookie headers and confirm the cookie is being set and sent on subsequent requests. Double-check your API Gateway settings to ensure it isn’t stripping or blocking cookies. You do not need to run a local Better Auth instance in NextJS—just ensure cookies are correctly propagated and accessible in server-side requests ([source](https://github.com/better-auth/better-auth/issues/3470)). <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/bc5dc948-f567-49ac-b4c7-6d263b43ee8a?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/bc5dc948-f567-49ac-b4c7-6d263b43ee8a?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/bc5dc948-f567-49ac-b4c7-6d263b43ee8a?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/bc5dc948-f567-49ac-b4c7-6d263b43ee8a?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/bc5dc948-f567-49ac-b4c7-6d263b43ee8a?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/bc5dc948-f567-49ac-b4c7-6d263b43ee8a?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/bc5dc948-f567-49ac-b4c7-6d263b43ee8a?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4044)
Author
Owner

@ArifAA14 commented on GitHub (Aug 16, 2025):

I managed to fix the cookie persistence issue by routing my requests through an API route so they are from the same domain, but the issue is that my

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

Still returns null even though the session cookie exists and is valid,
I also keep seeing the log

WARN [Better Auth]: No database configuration provided. Using memory adapter in development

However when I use the client hook

  const {
    data: session,
    isPending, //loading state
    error, //error object
    refetch, //refetch the session
  } = authClient.useSession();

  console.log(session);

This works, I am able to get the session. So now the only problem that remains is how can I use the Better Auth server-side functions since most my components are server components and turning them into client components is not an option for now.

Thanks.

@ArifAA14 commented on GitHub (Aug 16, 2025): I managed to fix the cookie persistence issue by routing my requests through an API route so they are from the same domain, but the issue is that my ``` const session = await auth.api.getSession({ headers: await headers(), }); ``` Still returns null even though the session cookie exists and is valid, I also keep seeing the log `WARN [Better Auth]: No database configuration provided. Using memory adapter in development ` However when I use the client hook ``` const { data: session, isPending, //loading state error, //error object refetch, //refetch the session } = authClient.useSession(); console.log(session); ``` This works, I am able to get the session. So now the only problem that remains is how can I use the Better Auth server-side functions since most my components are server components and turning them into client components is not an option for now. Thanks.
Author
Owner

@dosubot[bot] commented on GitHub (Aug 16, 2025):

The reason auth.api.getSession() returns null in your NextJS server components is that, without a database config, Better Auth falls back to a memory adapter—which is ephemeral and not connected to your Lambda backend. This is why you see the warning about no database configuration and why session retrieval fails server-side, even though the client hook works (because it makes network requests to your real backend) [source].

To get server-side session data in NextJS when your auth server is remote, you need to make an HTTP request from your server component or API route to your Lambda's /api/auth/get-session endpoint, forwarding the user's cookies. For example:

import { cookies } from "next/headers";

export async function getServerSession() {
  const cookieHeader = cookies().toString();
  const res = await fetch(`${process.env.AUTH_API_URL}/get-session`, {
    headers: { Cookie: cookieHeader },
    credentials: "include",
  });
  if (!res.ok) return null;
  return await res.json();
}

Then call await getServerSession() in your server component. This approach ensures your server-side code talks directly to the remote Better Auth server, which has DB access and can validate the session [source].

You do not need to recreate the Better Auth server in NextJS—just proxy server-side session lookups to your Lambda backend. The memory adapter warning is expected if you instantiate Better Auth locally without a DB config; it doesn't affect the client, but it means local server-side lookups won't work [source].

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Aug 16, 2025): <!-- Answer --> The reason `auth.api.getSession()` returns null in your NextJS server components is that, without a database config, Better Auth falls back to a memory adapter—which is ephemeral and not connected to your Lambda backend. This is why you see the warning about no database configuration and why session retrieval fails server-side, even though the client hook works (because it makes network requests to your real backend) [[source](https://github.com/better-auth/better-auth/blob/ef481d8dcce32d377b412ad1a96ecb8e604c1787/packages/better-auth/src/api/index.ts)]. To get server-side session data in NextJS when your auth server is remote, you need to make an HTTP request from your server component or API route to your Lambda's `/api/auth/get-session` endpoint, forwarding the user's cookies. For example: ```ts import { cookies } from "next/headers"; export async function getServerSession() { const cookieHeader = cookies().toString(); const res = await fetch(`${process.env.AUTH_API_URL}/get-session`, { headers: { Cookie: cookieHeader }, credentials: "include", }); if (!res.ok) return null; return await res.json(); } ``` Then call `await getServerSession()` in your server component. This approach ensures your server-side code talks directly to the remote Better Auth server, which has DB access and can validate the session [[source](https://github.com/better-auth/better-auth/pull/3160)]. You do not need to recreate the Better Auth server in NextJS—just proxy server-side session lookups to your Lambda backend. The memory adapter warning is expected if you instantiate Better Auth locally without a DB config; it doesn't affect the client, but it means local server-side lookups won't work [[source](https://github.com/better-auth/better-auth/blob/ef481d8dcce32d377b412ad1a96ecb8e604c1787/packages/better-auth/src/api/index.ts)]. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/3b157643-8ec4-4d23-bd9e-3fbe75b9805a?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/3b157643-8ec4-4d23-bd9e-3fbe75b9805a?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/3b157643-8ec4-4d23-bd9e-3fbe75b9805a?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/3b157643-8ec4-4d23-bd9e-3fbe75b9805a?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/3b157643-8ec4-4d23-bd9e-3fbe75b9805a?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/3b157643-8ec4-4d23-bd9e-3fbe75b9805a?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/3b157643-8ec4-4d23-bd9e-3fbe75b9805a?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4044)
Author
Owner

@anmol-fzr commented on GitHub (Aug 16, 2025):

Hey @ArifAA14, Refer to this code https://github.com/anmol-fzr/scam-vault/tree/master/packages/auth
this code runs on cloudflare workers, serverless runtime like AWS lambda, with hono

@anmol-fzr commented on GitHub (Aug 16, 2025): Hey @ArifAA14, Refer to this code https://github.com/anmol-fzr/scam-vault/tree/master/packages/auth this code runs on cloudflare workers, serverless runtime like AWS lambda, with hono
Author
Owner

@ArifAA14 commented on GitHub (Aug 16, 2025):

Hey, thanks for the help.

I managed to make it work finally, all I had to do was build a server action as follows and not rely on auth.api.getSession() from better-auth in NextJS.

import { cookies } from "next/headers";

export async function getServerSession() {
  const cookieHeader = cookies().toString();
  const res = await fetch(`${process.env.AUTH_API_URL}/get-session`, {
    headers: { Cookie: cookieHeader },
    credentials: "include",
  });
  if (!res.ok) return null;
  return await res.json();
}

For the cookie persistence issues, I proxied all the API calls to my API Gateway using NextJS API Routes

api/auth/[...all]/route.ts

import { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  return forwardAuthRequest(request);
}

export async function POST(request: NextRequest) {
  return forwardAuthRequest(request);
}

async function forwardAuthRequest(request: NextRequest) {
  const url = new URL(request.url);
  const authServerUrl = `${process.env.AWS_API_GATEWAY_URL}/api/auth${url.pathname.replace('/api/auth', '')}`;

  const response = await fetch(authServerUrl, {
    method: request.method,
    headers: request.headers,
    body: request.method !== 'GET' ? await request.text() : undefined,
  });

  return new Response(response.body, {
    status: response.status,
    headers: response.headers,
  });
}

Thanks for the help everyone!

@ArifAA14 commented on GitHub (Aug 16, 2025): Hey, thanks for the help. I managed to make it work finally, all I had to do was build a server action as follows and not rely on auth.api.getSession() from better-auth in NextJS. ``` import { cookies } from "next/headers"; export async function getServerSession() { const cookieHeader = cookies().toString(); const res = await fetch(`${process.env.AUTH_API_URL}/get-session`, { headers: { Cookie: cookieHeader }, credentials: "include", }); if (!res.ok) return null; return await res.json(); } ``` For the cookie persistence issues, I proxied all the API calls to my API Gateway using NextJS API Routes **api/auth/[...all]/route.ts** ``` import { NextRequest } from 'next/server'; export async function GET(request: NextRequest) { return forwardAuthRequest(request); } export async function POST(request: NextRequest) { return forwardAuthRequest(request); } async function forwardAuthRequest(request: NextRequest) { const url = new URL(request.url); const authServerUrl = `${process.env.AWS_API_GATEWAY_URL}/api/auth${url.pathname.replace('/api/auth', '')}`; const response = await fetch(authServerUrl, { method: request.method, headers: request.headers, body: request.method !== 'GET' ? await request.text() : undefined, }); return new Response(response.body, { status: response.status, headers: response.headers, }); } ``` Thanks for the help everyone!
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

@ArifAA14 I am getting the same issue can you help me pls

@kuldeepsaini23 commented on GitHub (Jan 3, 2026): @ArifAA14 I am getting the same issue can you help me pls
Author
Owner

@ArifAA14 commented on GitHub (Jan 3, 2026):

@kuldeepsaini23 Please provide further details or refer to my solution which I mentioned in a comment above.

@ArifAA14 commented on GitHub (Jan 3, 2026): @kuldeepsaini23 Please provide further details or refer to my solution which I mentioned in a comment above.
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

@ArifAA14
https://github.com/better-auth/better-auth/issues/7105#issuecomment-3707077032
Even I tried your solution also. Maybe I am doing something wrong. Also, if possible, can we connect on Discord, please? My Discord is: kuldeepsaini

@kuldeepsaini23 commented on GitHub (Jan 3, 2026): @ArifAA14 https://github.com/better-auth/better-auth/issues/7105#issuecomment-3707077032 Even I tried your solution also. Maybe I am doing something wrong. Also, if possible, can we connect on Discord, please? My Discord is: kuldeepsaini
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1722