Server, client and data · Lesson 6 of 16
Fetching data on the server
Async components, waterfalls, Promise.all, and data from Supabase.
A Server Component can be async, so you fetch data with await right inside it: no useEffect, no loading state, no in-between API. This code never reaches the browser, so secret keys are safe.
// app/dashboard/page.tsx
import { createClient } from "@/utils/supabase/server"
export default async function Dashboard() {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
// ❌ Waterfall: the second query waits for the first for no reason
// const courses = await getCourses(user.id)
// const badges = await getBadges(user.id)
// ✅ Independent queries in parallel
const [courses, badges] = await Promise.all([getCourses(user!.id), getBadges(user!.id)])
return <p>{courses.length} courses · {badges.length} badges</p>
}Sequential: courses (300ms) then badges (300ms) = 600ms
Parallel with Promise.all: both together = 300ms
Waterfalls are the most common cause of slow pages. Start all independent requests together.
Quick question
A page loads the user, then their courses (needs the user id), plus announcements (independent). Best order?
Exercise
getCourses and getBadges each take 200 ms. Fetch them together and print 2 courses, 3 badges, then fast if the total took under 350 ms (otherwise slow).
2 courses, 3 badges fast
const wait = (ms, value) => new Promise((r) => setTimeout(() => r(value), ms)) const getCourses = () => wait(200, ["React", "SQL"]) const getBadges = () => wait(200, ["streak", "first-run", "boss"]) const start = Date.now() const courses = await getCourses() const badges = await getBadges() console.log(courses.length + " courses, " + badges.length + " badges") console.log(Date.now() - start < 350 ? "fast" : "slow")
Learn more from
Played 0 of 2 games
Sign in to save your progress and earn XP.