supabase icon indicating copy to clipboard operation
supabase copied to clipboard

`serverSupabaseUser` is very slow (adds about 200-400ms)

Open madebyfabian opened this issue 3 years ago • 8 comments

Hi there, first of all, this is an awesome module, helps me much to build on nuxt3 and supabase. I noticed something strange. In nuxt server api routes, when using serverSupabaseUser like in the docs, this adds about 300-400ms to a request. I deployed the exact same code with and without serverSupabaseUser and the request with it took on average 550ms, and without it only 150ms on average.

With

Here is my test implementation (/api/test) which takes about 550ms:

import { serverSupabaseUser } from '#supabase/server'

export default defineEventHandler(async event => {
	const startTime = +new Date()
	console.log(startTime, 'start')
	const serverAuthUser = await serverSupabaseUser(event)
	if (!serverAuthUser) return sendError(event, createError({ statusCode: 401 }))

	console.log(+new Date(), 'end', { took: +new Date() - startTime })
	return true
})

Bildschirm­foto 2022-11-27 um 12 25 24

The logs:

1669548455166 start
1669548455296 end { took: 130 }
1669548423842 start
1669548424159 end { took: 317 }
1669548421038 start
1669548421166 end { took: 128 }
1669548418952 start
1669548419071 end { took: 119 }

Without

And here without it, just removed the serverSupabaseUser

export default defineEventHandler(async event => {
	const startTime = +new Date()
	console.log(startTime, 'start')

	console.log(+new Date(), 'end', { took: +new Date() - startTime })
	return true
})

Bildschirm­foto 2022-11-27 um 12 32 46

The logs:

1669548794478 start
1669548794478 end { took: 0 }
1669548791982 start
1669548791982 end { took: 0 }
1669548789446 start
1669548789446 end { took: 0 }
1669548786949 start
1669548786949 end { took: 0 }

Version

@nuxtjs/supabase: 0.3.0 nuxt: 3.0.0

Reproduction Link

Use the temporary-test-routes branch from this repo: https://github.com/madebyfabian/zingio/tree/temporary-test-routes

Steps to reproduce

  1. Deploy new nuxt project with nuxt/supabase to for example vercel
  2. Create a /server/api/test.ts with the contents above
  3. Deploy it with and without useSupabaseUser

What is Expected?

That useSupabaseUser only reads cookies and should only take minimal time. a

What is actually happening?

I suppose every useSupabaseUser call calls supabase.auth.getUser(), which loads the user object live from the database all the time. This does not seem to be an efficient solution, since it's adding many time to basically all requests that use it, for example only to validate if the current user id is allowed to access specific data.

madebyfabian avatar Nov 27 '22 11:11 madebyfabian

See on how to avoid this additional api call happening in supabase.auth.getUser() behind the scenes: https://github.com/supabase/supabase/issues/491

madebyfabian avatar Dec 08 '22 00:12 madebyfabian

@madebyfabian Have you found a solution/workaround for this? 🤔

warflash avatar Aug 22 '23 15:08 warflash

@warflash Hey there! Actually not really. Still using it as it is. But haven't updated the project in months, so maybe with the new 1.0 release of this module, things got faster.

madebyfabian avatar Aug 23 '23 19:08 madebyfabian

This is still slow. Did console.time and console.timeEnd and I get 600ms to even 1.5 seconds

AmitJoki avatar Sep 03 '23 01:09 AmitJoki

Any update on this? @madebyfabian

antoniputra avatar Nov 08 '23 22:11 antoniputra

@antoniputra Nothing new from my side. I'm not super into the implementation, but in my understanding, this code https://github.com/nuxt-modules/supabase/blob/main/src/runtime/server/services/serverSupabaseUser.ts is loading the user form the supabase API everytime the method is called. If this is something that has to be done for security reasons, than I think this is issue is not fixable.

madebyfabian avatar Nov 14 '23 16:11 madebyfabian

What we did is grab the jwt from the headers of the request, verify and parse it on the server and get user data injected into server context that way, avoiding that function entirely. Perhaps that's a solution for some of you

warflash avatar Nov 14 '23 16:11 warflash

I think this is a totally valid method, we can use the JWT_SECRET to locally decode (and validate !!) and prevent doing too many requests. We just need to check where and when the token is refreshed though, to refresh it by moments

We could implement this method if the user configures it in the module options, wdyt ?

noook avatar Mar 14 '24 00:03 noook