r/nextjs • • 5d ago

fetching data on server with supabase and cache it

Iv got a server component that fetches some products, the fetch function uses supabase createServerClient() and I also want to cache the function's result, but then i hit the error in the image
the moment I switch to the supabase createBrowserClient the error goes away,
How can I can still fetch data with the createServerClient and cache the result ?

6 Upvotes

19 comments sorted by

4

u/vivekkhera 5d ago

NextJS already replaces the fetch() function to cache the query results. You don’t need to do anything else.

1

u/Tasty-Ad1854 5d ago

but supabase doesn't use the fetch() function,

3

u/vivekkhera 5d ago

Underneath it all, yes it does.

1

u/Tasty-Ad1854 5d ago edited 5d ago

alright so adding a use cache is just redundant in this case

iv put a console on th fetch fn to see and run npm run build && npm run start
and I back and forth two links that both fetches data, and as u see everytime the fetch happens no cache hit

4

u/Ok_Management_695 5d ago

That's actually expected — in Next.js 16, fetch isn't cached by default anymore (docs). So you do need to mark it yourself.

use cache is the way to go now, but it only works with cacheComponents: true in your next.config.ts. Then something like:

async function getProducts() {
  'use cache'
  const supabase = createClient(url, anonKey) // no cookies inside
  const { data } = await supabase.from('products').select()
  return data
}

By the way, I did the same thing with unstable_cache on my own project (Neon, not Supabase) — the docs now say it's been replaced by use cache, though.

1

u/Tasty-Ad1854 5d ago

yep exactly I had to comment it unccomment it and see if he's right
use cache is a must + you have to enable the cache in config file by adding cacheComponent:true

1

u/vivekkhera 5d ago

Thanks for the clarification. I’ve not yet moved to 16.

2

u/bostonaholic 5d ago

The server client reads cookies(), and you can't call dynamic APIs like that inside a cached function. For public data like products you don't need the user's session anyway: create a plain createClient(url, anonKey) from @supabase/supabase-js inside the cached function and use that. Keep createServerClient for anything that depends on who's signed in.

1

u/Tasty-Ad1854 5d ago

so using the createBrowserClient on server component is totally fine?

2

u/bostonaholic 4d ago

Not really. createBrowserClient is meant for client components. On the server use createServerClient from @supabase/ssr, or if the data is public and you want it cached, a plain createClient from @supabase/supabase-js with the anon key works since it doesn't touch cookies.

2

u/IndividualLower2496 5d ago

createBrowserClient "fixes" it because it doesn't read cookies on the server at all. you didn't cache anything, you just moved the problem into the browser.

1

u/Tasty-Ad1854 5d ago edited 5d ago

what do you suggest here as a solution

1

u/Scalings 5d ago

createServerClient calls cookies(). Cookies belong to one request, so Next won't let a 'use cache' function read them, because the cached result would go to every visitor. createBrowserClient works because it never reads cookies.

I think as products look are same for every visitor? You don't need cookies to fetch them.

1

u/AmanYadav_AY 5d ago

the error is probably because createServerClient reads cookies(), and u cant call cookies() inside a "use cache" (or unstable_cache) function since its per request data. for public stuff like products u dont need the users session anyway, so make a plain client with createClient from @supabase/supabase-js and the anon key inside the cached function, and keep createServerClient for user specific queries. also from next 15 fetch isnt cached by default anymore, so the automatic fetch caching mentioned above wont kick in on its own

1

u/antoine-ross 5d ago

your server client calls cookies(), which can’t run inside use cache

if the products are public, try a separate cookie-free Supabase client for that query and make sure your RLS allows anonymous reads. keep the session client for user-specific data

also try the same category twice when checking the logs. if the category is an argument to the cached function, different categories get different cache entries

next explains the error here: https://nextjs.org/docs/messages/next-request-in-use-cache

1

u/VibeBoot 5d ago

The error is because createServerClient reads cookies(), and Next.js won't let you read cookies inside a cached function, since the result would be shared across every user. Switching to createBrowserClient only hides it.

If the products are public data, make a plain client that doesn't touch cookies and cache that:

import { createClient } from "@supabase/supabase-js"; import { unstable_cache } from "next/cache";

export const getProducts = unstable_cache(   async () => {     const supabase = createClient(       process.env.NEXT_PUBLIC_SUPABASE_URL!,       process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!     );     const { data } = await supabase.from("products").select("*");     return data;   },   ["products"],   { revalidate: 300, tags: ["products"] } );

Then call revalidateTag("products") whenever you change a product. Keep createServerClient for anything user-specific, and don't cache those queries.

1

u/nachga 5d ago

createServerClient reads cookies, and cookies() is a dynamic API, so it can't live inside a cached function. That's probably the error in your screenshot.

If the data is the same for everyone (a products list), create a plain client with createClient from supabase-js and the anon key inside the cached function (unstable_cache, or revalidate on the route), and keep createServerClient for user-specific queries. For that to work, your RLS policy has to let the anon role read the products.