N
Neon8mo ago
rival-black

fetching data on the client (like supabase)

what's the "best practice" for fetching data that needs to be on the client? i'm looking at migrating from supabase, so all of the data fetching that i have right now would need to change completely - i have a lot of data fetching on the client with swr hooks + usequeries fetching data from supabase, so i'm thinking if this is the right approach to go with in the future or no as in is the supabase approach (fetching from client) "better" and transferrable to neon in any way? with rls setup (which i have) it seems like it should be fine but i don't know or should i migrate to fetching data from the server via actions etc? would require me to rewrite pretty much everything to swr / tanstack query, but is it overall the "better" approach long term? i'm kind of conflicted here since normally fetching db on the client is a nono but with RLS it seems.. more acceptable?
33 Replies
homely-rose
homely-rose8mo ago
Take a look at my Tanstack hooks
homely-rose
homely-rose8mo ago
GitHub
GitHub - daveyplate/neon-drizzle-tanstack: Use Drizzle from the fro...
Use Drizzle from the front end using Tanstack Query hooks, secured with Neon RLS - daveyplate/neon-drizzle-tanstack
homely-rose
homely-rose8mo ago
I'm working on the readme and documentation right now, and an SWR port in the future Fetching dynamic data on the client, in my opinion, is the future for sure. Supabase is pretty risky due to having no rate limiting, and they intentionally do this to surge your costs. Neon is working on their rate limiter. I use a Next.js middleware rewrite as a proxy to the Neon serverless HTTP endpoint, and route all my client side fetches through that rewrite, which just updates the JWT with the appropriate "aud" claim then rewrites it to Neon's HTTP endpoint This allows me to use Vercel firewall as a rate limiter (super low latency) But you could also use an LRU cache or Upstash as a rate limiter for a Neon HTTP proxy in any other platform or host Hopefully Neon officially releases rate limiting soon so we can just hit the serverless endpoint directly without any concerns But yea Supabase was already extremely unsafe and has no plans to fix it All it takes is 1 malicious actor with minimal coding knowledge to skyrocket your supabase costs by running a loop on your Postgrest or sending infinite Realtime messages in your public channel
rival-black
rival-blackOP8mo ago
wtf that's crazy, i had no idea - links to discussion one and two for anyone interested the query allowlist seems like a nice thing, would probably need to be a build thing though. still, very cool why do you have a proxy that rewrites the aud claim? wouldn't it make sense to set that on the client itself? don't think there would be a way to spoof it tbh - or are you using it as the rate limiter mainly? if so that makes sense, probably wouldn't have it on vercel though due to pricing the fact that this isn't well known is actually insane - i've had annoying experiences with supabase (schema generation for json isn't overridable etc) but never something this annoying from what i've seen in the other channel https://discord.com/channels/1176467419317940276/1303805647816757339/1328125006043021342 you're changing the aud to neon - won't that disable RLS (i might be wrong and the user key might be deeper in the jwt) overall, what's the difference between using these hooks and just putting the query itself into the tanstack fetcher? i see you have stuff like getFirst("books") which fetches from the books table - why this way and not just fetching with tanstack
homely-rose
homely-rose8mo ago
It's just a more simple way for me to write my requests. If I want books, I can just say useFindMany("books") It would work just fine to write a custom Tanstack everywhere
rival-black
rival-blackOP8mo ago
makes sense, just wondering what are the limitations around this
homely-rose
homely-rose8mo ago
Just runs Drizzle. As for the aud claim, I do that so that only requests going through my proxy are allowed My middleware just takes the Bearer and appends aud: "neon" to it This way no one can query the DB unless it goes through that rate limiter Once Neon is done with theirs, I can skip this step and 0$ cost thru vercel Since it'll just hit neon directly from react
rival-black
rival-blackOP8mo ago
makes sense i think
homely-rose
homely-rose8mo ago
I don't want the client to have a JWT that can hit the DB directly cuz they could go around the rate limiter But the front end code is the same, Drizzle queries from the front end, just sets a different fetchEndpoint as the rate limiter proxy
rival-black
rival-blackOP8mo ago
is there any estimate on the neon limiter? i know they don't want to build it wrong (which makes sense) but if it's in the terms of weeks / months etc
homely-rose
homely-rose8mo ago
Simple switch to turn it off when Neon rate limiter is ready without having to rewrite much TBH I don't know All I know is they have written it in their docs that they are working on it
rival-black
rival-blackOP8mo ago
also most things make sense but won't stuff like drop database be prevented by RLS? https://discord.com/channels/1176467419317940276/1303805647816757339/1328136418786021416
homely-rose
homely-rose8mo ago
I like the Vercel firewall in the meantime because it's really fast Yes You have to GRANT drop to authenticated for that to work you use GRANT select to authenticated then RLS to secure it GRANT handles what operations and columns are allowed (CLS)
rival-black
rival-blackOP8mo ago
yeah so that won't be necessary no unless you grant that permission.. which sounds like a bad idea
homely-rose
homely-rose8mo ago
then RLS handles what where statements and conditions for the data etc
rival-black
rival-blackOP8mo ago
haven't experimented with CLS, supabase abandoned it iirc
homely-rose
homely-rose8mo ago
Yea definitely don't grant DROP CLS is just a grant for selecting specific columns GRANT select (id, name) from users to authenticated for example won't let them select password I haven't set up the CLS yet I'm going to test it out, when I used supabase I just had a separate profiles table and replicated names and usernames there
rival-black
rival-blackOP8mo ago
alr alr sounds nice yeah have that setup with triggers too
homely-rose
homely-rose8mo ago
Yea if I can't get CLS to play nice with my hooks as I have them then I'll probably just keep auth tables admin only I'm using Better Auth
rival-black
rival-blackOP8mo ago
makes sense. i might go with workos auth. haven't checked out better-auth yet 🤔
homely-rose
homely-rose8mo ago
It could work idk, I use better-auth to own all the auth data in my Neon db
homely-rose
homely-rose8mo ago
I built a shadcn UI package for better auth https://github.com/daveyplate/better-auth-ui and a tanstack query package for the JWT plugin
GitHub
GitHub - daveyplate/better-auth-ui: Premade shadcn better-auth card...
Premade shadcn better-auth cards & forms. Contribute to daveyplate/better-auth-ui development by creating an account on GitHub.
rival-black
rival-blackOP8mo ago
hmm. selfhosting auth makes sense for that reason, had issues with supabase auth though so don't want to deal with the same issues myself. on the other hand, looking at what they do i'm not sure if they might be doing it the wrong way
homely-rose
homely-rose8mo ago
I don't trust supabase tbh I told them about the security hole in realtime months ago and they never addressed it Seems intentionally abusable
rival-black
rival-blackOP8mo ago
now i don't either. felt weird from the start, no presigning s3 URLs etc. the abuse vector is very large and there are no "defaults" for stuff like this
homely-rose
homely-rose8mo ago
They told me they could disable realtime on the backend for my entire project But like. They force every single project anyone creates to have realtime accessible
rival-black
rival-blackOP8mo ago
i don't have a usecase for realtime. the only thing i had it for was streaming updates from the users table on subscription changes + website currency changes, but that was it. tanstack query can literally do the same and better
homely-rose
homely-rose8mo ago
And yea their docs encourage using Postgrest from the client with no protection So most ppl using it are open to attacks that will cost $$ and make them profit
rival-black
rival-blackOP8mo ago
wdym by "no protection" here
homely-rose
homely-rose8mo ago
they don't have any ratelimiting on postgrest api infinite egress with a simple js loop
rival-black
rival-blackOP8mo ago
there aren't any rate limit options on supabase itself
homely-rose
homely-rose8mo ago
not for their rest api aka supabase-js
rival-black
rival-blackOP8mo ago
which is the way everyone fetches data - there's a default limit of 50k rows returned but like bro

Did you find this page helpful?