redirect() & notFound()

Short-Circuit Rendering From Server Code

redirect() & notFound()

Call redirect() to send the user elsewhere or notFound() to render not-found.tsx straight from a server component.

4 min read Level 2/5 #nextjs#redirect#navigation
What you'll learn
  • Use `redirect()` from `next/navigation`
  • Use `notFound()` to render the closest `not-found.tsx`
  • Know the difference between `redirect` and `permanentRedirect`

Server Components are async functions, but you cannot return a Redirect element. Next.js provides helpers that throw special errors the framework catches and converts into the right server response.

redirect()

Call redirect(url) to send the user to another route. It works in server components, route handlers, and server actions.

// app/dashboard/page.tsx
import { redirect } from 'next/navigation';
import { getSession } from '@/lib/auth';

export default async function Dashboard() {
  const session = await getSession();
  if (!session) redirect('/login');
  return <h1>Welcome, {session.name}</h1>;
}

redirect does not return — it throws under the hood, so code after it does not run.

permanentRedirect()

For SEO-meaningful permanent moves, use permanentRedirect. It uses an HTTP 308 status code, so search engines update their indexes.

import { permanentRedirect } from 'next/navigation';

export default function OldUrlPage() {
  permanentRedirect('/new-url');
}

Use it for actual URL changes. Use redirect for everything else.

notFound()

Call notFound() from a server component to render the closest not-found.tsx.

// app/blog/[slug]/page.tsx
import { notFound } from 'next/navigation';

export default async function PostPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  const post = await fetchPost(slug);
  if (!post) notFound();

  return <article>{post.title}</article>;
}

If no not-found.tsx exists for the segment, Next.js walks up the tree and uses the nearest one — falling back to the framework default.

In Route Handlers

These helpers also work in route.ts files. redirect() will return a 307 (or 308 for the permanent variant). notFound() returns a 404. Combine them with auth checks at the top of your handler to keep guards clean.

The next lesson is the last in this section — per-route configuration with route segment exports.

Route Segment Config →