Move to a new canonical URL
An entity's canonical URL changes after a mutation, such as a username update.
Next.js 16+ · Function
permanentRedirect permanently sends users to another relative or absolute URL. It is available in App Router components and server APIs, normally producing a 308 redirect and stopping rendering immediately.
Import permanentRedirect from next/navigation and call it when a route should permanently move to another URL. The call throws a NEXT_REDIRECT error and stops rendering the current route segment; the resulting behavior depends on the execution context.
permanentRedirect(path, type)| Name | Type | Description |
|---|---|---|
path | string | The relative or absolute URL to redirect to. |
type | 'replace' | 'push' | History behavior: 'replace' or 'push'. Defaults to 'push' in Server Actions and 'replace' elsewhere. |
Does not return a value; calling it throws a NEXT_REDIRECT error and terminates rendering.
import { permanentRedirect } from 'next/navigation'
export default async function Page({
params,
}: {
params: Promise<{ username: string }>
}) {
const { username } = await params
const profile = await getProfile(username)
if (profile.canonicalUsername !== username) {
permanentRedirect(`/profile/${profile.canonicalUsername}`)
}
return <h1>{profile.name}</h1>
}
async function getProfile(username: string) {
return { name: username, canonicalUsername: username }
}Redirects a profile request to its canonical username when the requested URL is outdated.
An entity's canonical URL changes after a mutation, such as a username update.
A streamed route must redirect while rendering UI.
A Server Action needs navigation after a form submission.
permanentRedirect permanently sends the user to another URL and accepts a path plus an optional history-navigation type. In ordinary contexts it produces a 308 response; in Server Actions, progressive-enhancement form submissions use 303 and JavaScript can perform client-side navigation.
Follow-up: How does it differ from redirect? permanentRedirect is intended for permanent moves and normally uses 308, whereas redirect is the temporary counterpart and normally uses 307.
The signature is permanentRedirect(path, type). path is a relative or absolute URL, while type is replace or push; replace is the default outside Server Actions, and push is the default in Server Actions.
Follow-up: Why might type matter? It controls whether the destination replaces the current browser-history entry or adds a new one.
It can be used in Server Components, Client Components, Route Handlers, and Server Functions. In a streaming context, Next.js inserts a meta tag so the client performs the redirect.
Follow-up: What happens if it is called inside a try block? Its thrown NEXT_REDIRECT error can be caught, so the call should be placed outside the try block in Server Actions and Route Handlers.
redirectnotFoundNextResponse.redirectRoute HandlersServer Functions