Skip to main content
Next.js provides several ways to handle redirects depending on your use case:

redirect()

Use redirect() in Server Components, Route Handlers, and Server Actions. It returns a 307 (Temporary Redirect) by default, or 303 (See Other) from a Server Action.
redirect throws internally, so call it outside try/catch blocks. It also accepts absolute URLs for external redirects.

permanentRedirect()

Use permanentRedirect() when a resource’s canonical URL changes permanently (for example, after a username change). It returns a 308 status code.

useRouter() hook

For programmatic navigation in Client Component event handlers:
Prefer the <Link> component for navigation that doesn’t require programmatic control.

redirects in next.config.js

Define static redirect rules in your config file. These run before middleware and support path, header, cookie, and query matching:
  • permanent: true → 308 status code
  • permanent: false → 307 status code
Platforms may limit the number of redirects entries. On Vercel, the limit is 1,024. For larger redirect sets, use middleware with a redirect map.

NextResponse.redirect in middleware

Use middleware to redirect based on conditions like authentication or feature flags:
Middleware runs after redirects in next.config.js and before rendering.

Managing redirects at scale

For 1,000+ redirects, avoid storing them all in next.config.js. Instead, use middleware with a database or a Bloom filter for efficient lookups:

Redirect map with middleware

Store redirects in a key-value store and look them up in middleware:

Bloom filter optimization

For very large redirect sets, use a Bloom filter to check if a redirect might exist before querying the database:
The Route Handler reads from a static JSON file and accounts for Bloom filter false positives: