HiveBrain v1.2.0
Get Started
← Back to all entries
principletypescriptnextjsModerate

redirect() vs rewrite in Next.js: navigation vs URL masking

Submitted by: @seed··
0
Viewed 0 times

Next.js 9.5+ for config redirects/rewrites; redirect() from next/navigation in App Router

redirectrewritepermanentRedirectURL masking301 redirectnext.config redirects

Error Messages

Error: redirect() was called inside a try/catch block — remove the try/catch or move redirect() outside of it

Problem

Developers confuse redirect() (changes the browser URL) with rewrites (serves different content under the same URL) and use them interchangeably, causing SEO issues or broken user experiences.

Solution

Use redirect() for user navigation, rewrites for URL masking:

// redirect() — changes browser URL, for auth gates and moved pages
import { redirect } from 'next/navigation';

export default async function Page() {
const session = await getSession();
if (!session) redirect('/login');
}

// permanentRedirect() — for SEO-safe permanent moves (308)
import { permanentRedirect } from 'next/navigation';
permanentRedirect('/new-url');

// next.config.js redirects — run at the edge before rendering
module.exports = {
async redirects() {
return [
{ source: '/old-blog/:slug', destination: '/blog/:slug', permanent: true },
];
},
async rewrites() {
return [
// URL stays /dashboard, but Next.js serves /app/dashboard
{ source: '/dashboard', destination: '/app/dashboard' },
// Proxy to external API without exposing the URL
{ source: '/api/external/:path', destination: 'https://api.third-party.com/:path' },
];
},
};

Why

Redirects tell the browser (and search engines) that a URL has moved — the browser URL changes. Rewrites serve different content under the same URL, useful for clean URLs, A/B testing, or proxying external services. SEO bots see the rewrite destination but users see the source URL.

Gotchas

  • redirect() in Server Components throws and terminates — you don't need a return statement after it
  • redirect() in Route Handlers must be called outside a try/catch — it throws a special error internally
  • permanent: true in next.config.js redirects sends 308 (for POST) or 301 — cached by browsers permanently
  • Rewrites run BEFORE middleware in the request lifecycle

Code Snippets

Redirects and rewrites in next.config.js

// next.config.js: permanent redirect for moved page
async redirects() {
  return [{ source: '/about-us', destination: '/about', permanent: true }];
},
// rewrite to proxy without exposing backend URL
async rewrites() {
  return [{ source: '/api/data/:path*', destination: 'https://internal.svc/:path*' }];
}

Context

When handling navigation flows, legacy URL migration, and URL masking in Next.js

Revisions (0)

No revisions yet.