~3 min read • Updated Oct 28, 2025
Types of Redirects in Next.js
| API | Purpose | Where | Status Code |
|---|---|---|---|
| redirect | Redirect after mutation or event | Server Components, Server Actions, Route Handlers | 307 or 303 |
| permanentRedirect | Permanent redirect after canonical URL change | Server Components, Server Actions, Route Handlers | 308 |
| useRouter | Client-side navigation | Client Components | N/A |
| next.config.js | Redirect based on incoming path | Config file | 307 or 308 |
| NextResponse.redirect | Conditional redirect before response | Proxy | Any |
Using redirect
Redirect after creating or updating data:
'use server'
import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'
export async function createPost(id: string) {
revalidatePath('/posts')
redirect(`/post/${id}`)
}In Server Actions, it returns a 303 status code. Note: redirect throws an error and should be called outside try/catch blocks.
Using permanentRedirect
Redirect permanently after changing canonical URLs:
'use server'
import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'
export async function updateUsername(username: string) {
revalidateTag('username')
permanentRedirect(`/profile/${username}`)
}Using useRouter in Client Components
For navigation triggered by user interaction:
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}Redirects in next.config.js
For predefined redirects:
export async function redirects() {
return [
{ source: '/about', destination: '/', permanent: true },
{ source: '/blog/:slug', destination: '/news/:slug', permanent: true },
]
}Useful for URL structure changes or migrations. Note: Vercel limits redirects to 1,024 entries.
Conditional Redirects with Proxy
Redirect based on authentication or other conditions:
import { NextResponse, NextRequest } from 'next/server'
import { authenticate } from 'auth-provider'
export function proxy(request: NextRequest) {
if (!authenticate(request)) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}Managing Large Redirects with a Map
Store redirects in a JSON or database:
{
"/old": { "destination": "/new", "permanent": true },
"/blog/post-old": { "destination": "/blog/post-new", "permanent": true }
}Read from Edge Config or Redis and redirect accordingly.
Optimizing with Bloom Filter
For fast lookup of redirect paths:
- Use Bloom Filter to check existence
- If matched, fetch redirect data from Route Handler
- Send redirect response with appropriate status code
Conclusion
Next.js offers flexible redirect strategies — from simple navigation to scalable proxy-based solutions. By choosing the right method, you can build a smooth, secure, and maintainable user experience.
Written & researched by Dr. Shahin Siami