# Server Side Next.js Redirect: The Complete SEO Implementation Guide

> Master server side Next.js redirects for SEO. Implement permanent or temporary redirects easily using next navigations or NextResponse for optimal search engine performance.

- Repository: [Vercel/next.js](https://github.com/vercel/next.js)
- Tags: how-to-guide
- Published: 2026-02-19

---

**Use `permanentRedirect()` for 308 permanent redirects or `redirect()` for 307 temporary redirects from `next/navigation` in App Router Server Components and Route Handlers, or `NextResponse.redirect()` with explicit status codes in Middleware, to ensure search engines receive proper HTTP status headers without executing client-side JavaScript.**

Implementing a **server side Next.js redirect** is critical for preserving search rankings when migrating URLs or restructuring content. According to the vercel/next.js source code, the framework provides optimized helpers that issue HTTP-level redirects with correct status codes, eliminating client-side round trips that can confuse search engine crawlers.

## App Router: Server Components and Route Handlers

The App Router provides dedicated navigation utilities in [`packages/next/src/client/components/redirect.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/client/components/redirect.ts) that throw `RedirectError` instances caught by the runtime to generate HTTP responses.

### Permanent Redirects with `permanentRedirect()`

For SEO-friendly permanent moves, use `permanentRedirect()` which returns a **308 Permanent Redirect** status. In [`packages/next/src/client/components/redirect-status-code.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/client/components/redirect-status-code.ts), this maps to `RedirectStatusCode.PermanentRedirect`.

```tsx
// app/old-page/page.tsx
import { permanentRedirect } from 'next/navigation'

export default function OldPage() {
  // Throws RedirectError, caught by runtime, returns 308 with Location header
  permanentRedirect('/new-page')
}

```

### Temporary Redirects with `redirect()`

For temporary moves, `redirect()` issues a **307 Temporary Redirect** by default, preserving the HTTP method used in the original request.

```tsx
// app/api/redirect/route.ts
import { redirect } from 'next/navigation'

export async function GET() {
  // 307 temporary redirect
  redirect('/temporary-destination')
}

```

### Advanced: Using `getRedirectError` Directly

For custom logic requiring manual error throwing, use the internal `getRedirectError` helper. This achieves the same result as `redirect()` but allows dynamic status code configuration.

```ts
// lib/redirect-utils.ts
import { getRedirectError } from 'next/navigation'

export function redirectTo(url: string) {
  // Manually throw the internal error – same effect as `redirect()`
  throw getRedirectError(url, 'replace', 307)
}

```

## Middleware and Edge Runtime

For redirects that must execute before hitting application logic, Next.js Middleware running in the Edge Runtime uses `NextResponse.redirect()` as shown in [`packages/next/src/server/web/error.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/server/web/error.ts).

```ts
// middleware.ts
import { NextResponse } from 'next/server'

export function middleware(request) {
  const url = new URL(request.url)
  if (url.pathname === '/old-blog') {
    // Explicit 301 permanent redirect
    return NextResponse.redirect(new URL('/new-blog', request.url), { status: 301 })
  }
  return NextResponse.next()
}

```

This approach allows precise control over status codes (301 or 302) while executing at the edge, enabling instant response caching without invoking Node.js server processes.

## Pages Router API Routes

For the legacy Pages Router, implement redirects using the Node.js response object directly when running outside the Edge Runtime.

```ts
// pages/api/old.ts
export default function handler(req, res) {
  res.writeHead(301, { Location: '/new' })
  res.end()
}

```

## Why Server-Side Redirects Matter for SEO

Using the built-in **server side Next.js redirect** APIs provides specific search engine optimization advantages over client-side navigation:

- **No Client-Side Execution**: Crawlers receive the `Location` header immediately without executing JavaScript, ensuring the redirect is followed correctly and indexation targets the destination URL.
- **Correct Status Codes**: The `308` permanent redirect (used by `permanentRedirect()`) preserves POST request methods during the redirect, while `301` remains available in Middleware for classic permanent redirects that method-shift to GET.
- **Edge Caching**: Next.js caches redirect responses in the Edge Runtime, reducing latency for subsequent crawler requests and minimizing server load.

## Summary

- Use `permanentRedirect()` from `next/navigation` for 308 permanent redirects in App Router Server Components, as implemented in [`packages/next/src/client/components/redirect.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/client/components/redirect.ts).
- Use `redirect()` from `next/navigation` for 307 temporary redirects in Route Handlers.
- Use `NextResponse.redirect()` in Middleware for edge-level redirects with customizable 301/302 status codes.
- Reference [`packages/next/src/client/components/redirect-status-code.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/client/components/redirect-status-code.ts) for the enum definitions of supported status codes.
- Always prefer server-side redirects over `useRouter()` client-side navigation for SEO-critical URL changes to ensure search engines properly transfer ranking signals.

## Frequently Asked Questions

### What is the difference between 301 and 308 redirects in Next.js?

Next.js supports both status codes: `301` (classic permanent redirect) available in Middleware via `NextResponse.redirect()`, and `308` (permanent redirect) used by `permanentRedirect()` in the App Router. While both indicate permanent moves, `308` preserves the original HTTP method (POST stays POST), whereas `301` historically causes clients to switch POST requests to GET.

### Can I use `redirect()` in a Client Component?

No. The `redirect()` and `permanentRedirect()` functions from `next/navigation` are designed for Server Components and Route Handlers only. They function by throwing a `RedirectError` that the server runtime catches and converts into an HTTP response. For client-side navigation, use `useRouter()`, though this lacks the SEO benefits of server-side redirects.

### How do I handle dynamic URL redirects in Next.js Middleware?

Inspect the `request.nextUrl` pathname in your [`middleware.ts`](https://github.com/vercel/next.js/blob/main/middleware.ts) file, then construct the target URL dynamically before calling `NextResponse.redirect()`. This executes at the edge before the request reaches your application code, making it efficient for high-volume redirect rules and A/B testing scenarios.

### Do server-side redirects in Next.js affect page performance?

Server-side redirects improve perceived performance by eliminating the client-side JavaScript execution required for client-side navigation. When implemented in Middleware, the Edge Runtime caches redirect responses, meaning subsequent requests receive the `Location` header instantly without invoking Node.js server processes or database queries.