-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Server-side HTTP requests via getSession
usually get extremely slow on Vercel
#1535
Comments
So this has actually been asked several times before, and @iaincollins's reasoning is the following:
I am not sure what his opinion was on making an alternative method that would allow the user to deliberately do what they want accepting the consequences. @iaincollins? What do you think? Related: #1199, #947 (comment), #212 (comment), #212 (comment) and probably more. |
@balazsorban44 thanks for your quick response! Some deployment services (e.g. Vercel) bundle all the API routes into a single Lambda, so there should be no significant size difference between the fetch-based version and importing already bundled functions directly. The isomorphic |
I think something like this is reasonable in principle but we'd need to address how passing app configuration is handled in a consistent way in different environments (i.e. consistant behaviour that allows for, but doesn't assume, shared context for all functions). I've got ideas about how I'd like config to work the longer term, but I'm open to suggestions for interim solutions. |
This issue is particularly noticeable when Vercel's platform experiences additional latency - API calls to a protected endpoint simply start timing out. Anything we can do in userland to avoid the additional network request? |
To add a data point here: prisma/prisma#7009 (comment) This is a Prisma user who attributed the latency in his app to Prisma in the beginning. We then, with the help of @kripod, figured out that this might indeed be a Vercel deployment + Nextauth issue as described above. Fixing this in some way or protecting users in serverless environments would be very nice. (And yep, we know the pain of serverless deployments at Prisma as well. We are trying everything to make it nice for people, but some problems are just still unsolved. [which is totally not Vercel's fault by the way, they are doing an amazing job of making serverless usable in the first place - but now people use it 😆]) |
You can see the original comment what I used to base my answers on protecting our current implementation: #947 (comment) but I'm getting more and more convinced that this has indeed been a poor choice, especially when the reason behind it was to better support serverless environments. It seems to me that it kind of has the opposite effect of what the original implementation wanted to achieve. |
FYI I managed to roughly half the cold-boot impact by bypassing |
I created a temporary version at import {getServerSession} from "next-auth"
import {options} from "pages/api/auth/[...nextauth]"
export default Page(){
return null
}
export async function getServerSideProps(context) {
return {
props: {
session: await getServerSession(context, options),
},
}
} And in your Very interested if someone could check out if it helps. The |
Keen to check it out @balazsorban44 - is there a PR/branch I can look over? |
the code is only available locally currently it is just a quick and dirty implementation, so nothing to look at there. the more interesting part is if it makes any difference in performance. check out the above mentioned version |
We’ve been using the proposed I would love to see a similar API implemented in the upcoming versions of NextAuth, as it improves performance by a leap in serverless environments. |
this is up for a take to anyone who would likte to open a PR about this against |
I have created a branch https://github.com/walid-mokrani/next-auth/tree/feat/get-server-side if someone can look at it. |
@walid-mokrani looks promising, would you care to open a PR against our |
Documentation comes later, but have a look at these files to get the idea: https://github.com/nextauthjs/next-auth/blob/9aba57396c6776642ed743b60a266a29385652ac/app/pages/api/auth/%5B...nextauth%5D.ts https://github.com/nextauthjs/next-auth/blob/9aba57396c6776642ed743b60a266a29385652ac/app/pages/protected-ssr.js The API is not necessarily final yet, we might change the name or recommend the config to be moved to a |
This will also be the solution for #2850. That discussion made me aware that we have never actually updated the session cookie when |
TLDR
Here's my write up of changing to use Just as an update to other who are interested in the I use NextAuth heavily in my open source daily habit tracking application which uses Next (Full SSR Frontend + API) + NextAuth + Prisma + Postgres and is hosted on Vercel. This means all of my API functions are deployed as server less functions and I do all of my auth checking in server side rendering methods for my pages. Previously NextAuth's use of http
With the new getServerSession this removes http requests (2) and (4) because the SSR method is directly accessing the logic to retrieve the session without having to make an http request. Some notes about current implementation if you're looking to do this in your application
|
Also, @balazsorban44 THANK YOU! 😃 |
There won't be beta.8. Next stop is at stable v4. 😊 getServerSession won't launch officially yet, and considered experimental until documented, but hearing that it helped is awesome! |
getServerSession works for me locally, but it returns an error string when run on Vercel. Here is my API code: import { authOptions } from 'common/config/next-auth';
import type { NextApiRequest, NextApiResponse } from 'next';
import { getServerSession } from 'next-auth';
export default async (req: NextApiRequest, res: NextApiResponse) => {
// const session = await getSession({ req });
const session = await getServerSession({ req, res }, authOptions);
console.log('session: ', session);
res.status(200).json({ session });
} Here are my auth options: import { NextAuthOptions } from 'next-auth';
import CognitoProvider from 'next-auth/providers/cognito';
export const authOptions: NextAuthOptions = {
debug: true,
providers: [
CognitoProvider({
clientId: process.env.COGNITO_CLIENT_ID!,
clientSecret: process.env.COGNITO_CLIENT_SECRET!,
issuer: `https://cognito-idp.us-east-1.amazonaws.com/${process.env.COGNITO_USER_POOL_ID}`,
}),
],
secret: '...'
}; When running on Vercel getServerSession returns an HTML string containing the following (formatted for readability): <!DOCTYPE html>
<html lang=\"en\">
<head>
<meta charset=\"UTF-8\">
<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
<style>:root{--border-width:1px;--border-radius:0.3rem;--color-error:#c94b4b;--color-info:#157efb;--color-info-text:#fff}.__next-auth-theme-auto,.__next-auth-theme-light{--color-background:#fff;--color-text:#000;--color-primary:#444;--color-control-border:#bbb;--color-button-active-background:#f9f9f9;--color-button-active-border:#aaa;--color-seperator:#ccc}.__next-auth-theme-dark{--color-background:#000;--color-text:#fff;--color-primary:#ccc;--color-control-border:#555;--color-button-active-background:#060606;--color-button-active-border:#666;--color-seperator:#444}@media (prefers-color-scheme:dark){.__next-auth-theme-auto{--color-background:#000;--color-text:#fff;--color-primary:#ccc;--color-control-border:#555;--color-button-active-background:#060606;--color-button-active-border:#666;--color-seperator:#444}}body{background-color:var(--color-background);font-family:-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,Helvetica,Arial,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;margin:0;padding:0}h1{font-weight:400;margin-bottom:1.5rem;padding:0 1rem}h1,p{color:var(--color-text)}form{margin:0;padding:0}label{color:#666;display:block;font-weight:500;margin-bottom:.25rem;text-align:left}input[type]{background:var(--color-background);border:var(--border-width) solid var(--color-control-border);border-radius:var(--border-radius);box-shadow:inset 0 .1rem .2rem rgba(0,0,0,.2);box-sizing:border-box;color:var(--color-text);display:block;font-size:1rem;padding:.5rem 1rem;width:100%}input[type]:focus{box-shadow:none}p{font-size:1.1rem;line-height:2rem;margin:0 0 1.5rem;padding:0 1rem}a.button{line-height:1rem;text-decoration:none}a.button,a.button:link,a.button:visited,button{background-color:var(--color-background);color:var(--color-primary)}a.button,button{border:var(--border-width) solid var(--color-control-border);border-radius:var(--border-radius);box-shadow:0 .15rem .3rem rgba(0,0,0,.15),inset 0 .1rem .2rem var(--color-background),inset 0 -.1rem .1rem rgba(0,0,0,.05);font-size:1rem;font-weight:500;margin:0 0 .75rem;padding:.75rem 1rem;position:relative;transition:all .1s ease-in-out}a.button:hover,button:hover{cursor:pointer}a.button:active,button:active{background-color:var(--color-button-active-background);border-color:var(--color-button-active-border);box-shadow:0 .15rem .3rem rgba(0,0,0,.15),inset 0 .1rem .2rem var(--color-background),inset 0 -.1rem .1rem rgba(0,0,0,.1);cursor:pointer}a.site{color:var(--color-primary);font-size:1rem;line-height:2rem;text-decoration:none}a.site:hover{text-decoration:underline}.page{display:grid;height:100%;margin:0;padding:0;place-items:center;position:absolute;width:100%}.page>div{padding:.5rem;text-align:center}.error a.button{display:inline-block;margin-top:.5rem;padding-left:2rem;padding-right:2rem}.error .message{margin-bottom:1.5rem}.signin a.button,.signin button,.signin input[type=text]{display:block;margin-left:auto;margin-right:auto}.signin hr{border:0;border-top:1px solid var(--color-seperator);display:block;margin:1.5em auto 0;overflow:visible}.signin hr:before{background:var(--color-background);color:#888;content:\"or\";padding:0 .4rem;position:relative;top:-.6rem}.signin .error{background:#f5f5f5;background:var(--color-info);border-radius:.3rem;font-weight:500}.signin .error p{color:var(--color-info-text);font-size:.9rem;line-height:1.2rem;padding:.5rem 1rem;text-align:left}.signin>div,.signin form{display:block}.signin>div input[type],.signin form input[type]{margin-bottom:.5rem}.signin>div button,.signin form button{width:100%}.signin>div,.signin form{max-width:300px}.signout .message{margin-bottom:1.5rem}.logo{display:inline-block;margin-top:100px;max-height:150px;max-width:300px}.card{border:1px solid var(--color-control-border);border-radius:5px;margin:50px auto;max-width:-webkit-max-content;max-width:-moz-max-content;max-width:max-content;padding:20px 50px}.card .header{color:var(--color-primary)}.section-header{color:var(--brand-color)}</style>
<title>Error</title>
</head>
<body class=\"__next-auth-theme-auto\">
<div class=\"page\">
<div class=\"error\">
<style>\n :root {\n --brand-color: undefined;\n }\n </style>
<div class=\"card\">
<h1>Server error</h1>
<div class=\"message\">
<div>
<p>There is a problem with the server configuration.</p>
<p>Check the server logs for more information.</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html> The effective result of the test API I have above is: {
session: "<!DOCTYPE ...."
} No actual exception is thrown and nothing else is logged (debug mode is enabled in authOptions). Has anyone experienced this? |
@davudk What version of next-auth are you using? I had a very similar behavior when I was using next-auth@4.0.0-beta.7, when I upgraded to next-auth@0.0.0-pr.3222.41318883 these went away. |
@trentprynn Ah this was exactly it! Now it's working on my Vercel deployment and the difference in the session load speed is immense. Much better! Thanks |
Just to add another success story to this thread. I just migrated a project from v3 to v4 (to address these performance issues), and updated my server route to use One note, not necessarily related to
|
@SimplyComplexable fixed in #3222, part of the upcoming release. #3307 |
update: upgraded to next-auth@4.0.1 today and all is well |
Hi everyone! As a note, since undocumented, I still consider the feature experimental, and we might change the API when we finalize it. Cheers 🍻 |
Hello, and thanks a lot for taking care of this issue! I was wondering if that would be possible to make it also available for ./node_modules/openid-client/lib/helpers/deep_clone.js:1:33
Module not found: Can't resolve 'v8'
Import trace for requested module:
./node_modules/openid-client/lib/issuer.js
./node_modules/openid-client/lib/index.js
./node_modules/next-auth/core/lib/oauth/callback.js
./node_modules/next-auth/core/routes/callback.js
./node_modules/next-auth/core/routes/index.js
./node_modules/next-auth/core/index.js
./node_modules/next-auth/next/index.js
./pages/_app.tsx My use case is like the one in this thread where I want to load user data from SSR pages and have it served by a top-level context to all my components instead of having it called in every of my page. Do you think it's something feasible? |
In any case, To require auth on your entire page now only needs a single line though, using Middleware:
export { default } from "next-auth/middleware https://next-auth.js.org/configuration/nextjs
|
Heads up anyone using So we can include it in the documentation. The API might change, but the idea will be the same, to avoid the extra |
Describe the bug
Before further ado, here’s a comparison between a
/api/user/{id}
request which fetches/api/auth/session
through the network even on the server side, versus a/api/site/{id}
call, which isn’t protected viagetSession
. Unfortunately, there’s a quite large margin between response times.Steps to reproduce
Call
getSession
on the server side and observe that it makes an HTTP request instead of just calling functions locally.Expected behavior
Calls to
getSession
should be executed locally in a server environment. A separategetServerSession
method could be added as a non-isomorphic solution without any HTTP calls.Additional context
According to the official Next.js docs:
This seems to hurt performance badly.
Feedback
Documentation refers to searching through online documentation, code comments and issue history. The example project refers to next-auth-example.
Thank you for maintaining this wonderful library – it really helps a lot! 🙏
The text was updated successfully, but these errors were encountered: