Cold Boot Performance Issues
See original GitHub issueDescribe the bug
I have observed extended response times for any NextAuth
endpoint in the scenario of a cold boot of a serverless function. This is regardless of whatever method or encryption you’re using (JWT/database, encrypted and non-encrypted).
These performance issues are in the range of multiple seconds of response time. For context, ‘cold boot’ occurs in these scenarios:
- Launch a new version of an app on Vercel so that there is no pre-existing hot Lambda and hit the endpoint with a new request
- Hit the Lambda endpoint with concurrent requests
- Wait 15 mins for the Lambda endpoint cache to expire
Steps to reproduce
- Fresh
Next.js
application using the latest version. - Implement
next-auth
library using the standard implementation - Implement any provider, custom or pre-defined (I’ve used custom & Google for testing)
- Launch on Vercel (or run locally)
- Go to any endpoint provided by NextAuth (I’ve been using
<your deployment>/api/auth/session
for testing) - Note that on the initial request, it can take upward of
~5 seconds
to respond (this is regardless of whether they have a JWT cookie to decode or a database to connect to) - Repeated requests to the same endpoint once the function is ‘hot’ and available takes under
~100ms
Further to the above, I’ve noted that when ‘hot’, the /session
endpoint uses 131MB
of memory so to optimize serverless costs, we’ve adjusted our vercel.json
for /session
to provision itself with 192MB
of available memory as opposed to the default of 1GB
. In this scenario, the initial requests takes upward of ~9 seconds
.
Expected behavior Initial requests on cold functions don’t take over a second to respond, especially for those without an active session (e.g. no JWT cookie for stateless sessions).
Screenshots or error logs
I did some profiling as to what was taking the majority of the time in the aforementioned scenarios and got the following results from a Vercel function on the /session
endpoint using 192MB
of memory:
typeorm: 6241.299ms
prisma: 1.078ms
adapters: 6280.308ms
jwt: 480.770ms
parse-url: 0.546ms
logger: 0.304ms
cookie: 1.041ms
default-events: 0.649ms
default-callbacks: 0.378ms
providers: 0.301ms
callback-url-handler: 0.458ms
extend-req: 0.244ms
routes: 318.520ms
pages: 42.476ms
csrf-token-handler: 36.856ms
create-secret: 0.382ms
pkce-handler: 1.179ms
state-handler: 0.491ms
_NextAuthHandler: 19.533ms
session: 0.012ms
Additional context
It’s clear that most functions/libraries are fairly quick and performant but the real outlier here is typeorm
which is part of adapters
. This is included in the first line of the server index.js.
I’m not proficient with this library but at a glance, everything in adapters
only appears to be being used when someone provides a customer adapter
in the options or database
is being used to store sessions, neither of which is default to next-auth
and need to be explicitly set as stateless sessions is the default.
I tested my theory and removed the import adapters from '../adapters'
entirely, deployed and then attempted the /session
endpoint again and found it worked. More crucially it reduced the cold start response time to a more manageable ~2 seconds
. Furthermore, it reduced the memory usage from 131MB
to 94MB
, which meant we can reduce our memory allocation even further.
To this end, I propose that it doesn’t make sense to include this significant overhead in the majority of cases when users are using the next-auth
default config of stateless sessions. May I suggest we look to dynamically import the ./adapters
in the server/index.js
only in the situations where it’s necessary (e.g. user has configured database
sessions).
I’m also looking at other areas to optimize this initial load, specifically jwt
and routes
but clearly this is an improvement on what it was initially.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:17 (9 by maintainers)
Currently
typeorm
(andprisma
as well, actually) is pulled in/downloaded/bundled, no matter if you use a DB or not. (Or even if you use a custom adapter) https://github.com/nextauthjs/next-auth/blob/17b789822de64eb845e1e8e49ea83dbff56344f4/src/server/index.js#L1 https://github.com/nextauthjs/next-auth/blob/17b789822de64eb845e1e8e49ea83dbff56344f4/src/server/index.js#L89This will hopefully be fixed in #1682, but this will require that you will have to install
typeorm
yourself if you actually use it.In case you don’t rely on a database (or you will write your own adapter with a much smaller footprint), the bundle size will drastically drop. At least that is the intent. Follow the PR on the progress.
Before you folks close this - I just wanted to add that we’re experiencing a very similar issue but we’re not running our app on Lambda/Vercel - but in EKS and we’re seeing the same behavior: The first request always takes " a while" (6-15 seconds observed). We are also seeing periodic multi second delays occasionally. It feels very similar to what @mod-flux describes in their issue but rather than a lambda function cache expiring - it seems like this is present even when lambda is not involved.
We are not really using TypeORM in our application (other than next-auth using it internally). We could consider writing our own DB adapter using something like KnexJS - but what I don’t understand is whether next-auth would still load TypeORM even if we use a custom DB adapter?
For reference we’re using: