pealdevDOCS
Back to peal.dev

AUTH STARTER · SESSIONS & HELPERS

Sessions & helpers

Database sessions, not JWTs. Per-request caching. Three helpers cover 99% of session checks.

Sessions are stored in the session table. The cookie holds a session token — Better Auth looks it up on each request (with a 5-minute cookie cache, so the DB isn't hit every render). Easier to invalidate than JWTs, easier to inspect, easier to debug.

The three helpers

TypeScript
import {
  getSession,      // returns session | null
  requireSession,  // redirects to /sign-in if no session
  requireGuest,    // redirects to /dashboard if there IS a session
} from "@/lib/auth-helpers";

Use them like this

TypeScript
// A protected page (Server Component)
export default async function DashboardPage() {
  const session = await requireSession();
  return <p>Welcome, {session.user.name}</p>;
}

// An auth page — bounce logged-in users away
export default async function SignInPage() {
  await requireGuest();
  return <SignInForm />;
}

// An optional-session page
export default async function HomePage() {
  const session = await getSession();
  return session ? <Dashboard /> : <Landing />;
}

React cache() means one DB read per render

getSession is wrapped in React's cache(). Call it from your layout, from the page, from a server action — only ONE DB lookup happens per request. Use it freely.

Reading the session in Client Components

TypeScript
"use client";
import { useSession } from "@/lib/auth-client";

export function Profile() {
  const { data: session, isPending } = useSession();
  if (isPending) return <Skeleton />;
  if (!session) return <SignInPrompt />;
  return <p>{session.user.email}</p>;
}

We enable session.cookieCache in authConfig with a 5-minute TTL. The user's session payload is mirrored into a signed cookie, so most requests resolve without a DB read. Cleared automatically on sign-out.

Cookie cache means stale role for 5 minutes

If you ban a user or change their role, the cached cookie keeps the old payload until it expires. For most apps that's fine. If you need instant revocation, lower session.cookieCache.maxAge (or disable it).

Never trust the cookie cache for authorization decisions

Use it for personalization ("hi, name"). For "can this user delete this resource", always fetch fresh role from the DB inside the action. Cookie cache is a perf tool, not an authorization tool.