Wise Hustlers — Digital Product & App Development Studio Logo
Get Consultation
By Wise Hustler Admin8/23/20269 min read

Next.js App Router vs Pages Router in 2026: Is There Still a Reason to Choose Pages?

Next.js App Router vs Pages Router in 2026: Is There Still a Reason to Choose Pages?

# Next.js App Router vs Pages Router in 2026: Is There Still a Reason to Choose Pages?

TL;DR: As of Next.js 16.3 (August 2026), the App Router is where every new capability lands and create-next-app scaffolds it by default — but the Pages Router is not deprecated. Vercel has publicly committed to continued bug fixes and security patches for it across multiple major versions. Start new projects on the App Router; keep large, stable Pages Router apps on Pages unless you have a concrete reason to migrate.

Where things actually stand right now

It's worth separating community narrative from official position, because they've drifted apart.

What's true: Next.js 16 (released October 2025) made Turbopack the default bundler for both next dev and next build, and the default create-next-app template ships the App Router with no prompt to pick Pages instead. Subsequent releases — 16.2 (which stabilized the Build Adapters API) and 16.3 (August 2026, adding Instant Navigations and cutting dev-server memory usage by up to 90% via Turbopack disk caching and eviction) — have continued to ship features exclusively under app/. Cache Components and the use cache directive, the current caching model as of Next.js 16, are documented and implemented under the App Router's rendering model.

What's not true: there is no deprecation notice, no removal timeline, and no CLI warning for the Pages Router. Vercel's own position statement, "The Future of Next.js Pages Router" (Discussion #56655) — the answer the team points to whenever the question is re-asked, as in Discussion #61575 — commits to supporting pages/ development with bug fixes, improvements, and security patches for multiple major versions going forward, specifically so teams can migrate on their own schedule. What that commitment does not promise is new features: in practice the Pages Router is in maintenance mode, and everything new ships to app/ first. Running app/ and pages/ side by side in the same project is a supported, documented pattern, not a hack.

Security patching backs this up in practice, not just in a GitHub comment: Vercel's security releases have patched both branches concurrently — for example, versions 15.5.18 and 16.2.6 shipped together covering advisories for middleware bypass, denial-of-service, SSRF, cache poisoning, and cross-site scripting issues. If Pages were being sunset, it wouldn't be getting the same-day patch treatment as the current major.

So the honest framing for "next.js pages router deprecated" as a search query: not deprecated, but clearly not where the framework is investing. Those are different risk profiles, and they lead to different decisions depending on where your app is today.

The core architectural difference

Pages RouterApp Router
Directorypages/app/
Rendering defaultClient components, opt into SSR/SSG per pageServer Components by default
Data fetchinggetServerSideProps, getStaticProps, getInitialPropsasync/await directly in Server Components, plus fetch caching semantics
LayoutsManual, via _app.tsx / _document.tsx, re-renders on navNested layout.tsx, persists across navigations
StreamingNot supported nativelyBuilt in via loading.tsx and <Suspense>
Caching modelPer-function options (revalidate)Cache Components / use cache directive (Next.js 16+), explicit and code-level
Route handlersAPI Routes (pages/api)Route Handlers (app/api/.../route.ts)
New feature investmentSecurity/bug fixes onlyActive development (Turbopack defaults, Instant Navigations, Cache Components)

The practical difference developers feel first is data fetching and layout composition. Here's the same "fetch a list and render a shared shell" pattern in both.

Pages Router:

// pages/products/index.tsx
import type { GetServerSideProps } from "next";

type Product = { id: string; name: string };

export const getServerSideProps: GetServerSideProps<{
  products: Product[];
}> = async () => {
  const res = await fetch("https://api.example.com/products");
  const products: Product[] = await res.json();
  return { props: { products } };
};

export default function ProductsPage({
  products,
}: {
  products: Product[];
}) {
  return (
    <ul>
      {products.map((p) => (
        <li key={p.id}>{p.name}</li>
      ))}
    </ul>
  );
}

App Router:

// app/products/page.tsx
type Product = { id: string; name: string };

async function getProducts(): Promise<Product[]> {
  const res = await fetch("https://api.example.com/products", {
    next: { revalidate: 3600 }, // ISR-equivalent, per-request
  });
  return res.json();
}

export default async function ProductsPage() {
  const products = await getProducts();
  return (
    <ul>
      {products.map((p) => (
        <li key={p.id}>{p.name}</li>
      ))}
    </ul>
  );
}

No getServerSideProps wrapper, no props plumbing — the component itself is async and runs on the server. The tradeoff is a steeper mental model: Server Components vs Client Components, when "use client" is required, and how Suspense boundaries interact with streaming. Teams coming from Pages Router usually underestimate this learning curve on the first migration.

Performance: what actually changed

The biggest practical shift isn't a benchmark number, it's what ships to the browser by default. Pages Router sends the full page component (and its dependencies) to the client unless you specifically split it out, because everything under pages/ is a client component by default. App Router inverts that: components are Server Components unless marked "use client", so JavaScript that only needs to run once on the server — data fetching, formatting, anything that doesn't handle a browser event — never reaches the client bundle at all. That's a bundle-size effect, not a raw rendering-speed one, and it scales with how much of your UI is genuinely static versus interactive.

On the tooling side, Turbopack becoming the default bundler in Next.js 16 affects both routers equally during development and build, and 16.3's dev-server memory reduction (up to 90% in the disk-caching and eviction paths introduced that release) is a next dev improvement independent of which router you use. Don't conflate "Next.js 16 is faster" with "App Router is faster" — some of the 2026 performance story applies to any Next.js 16 project regardless of router.

When Pages Router is still the right call

  • You have a large, stable app with no active feature roadmap. Migrating purely for architecture's sake, with no bug or performance problem to fix, is a real cost with no roadmap payoff. Security patches keep arriving either way.
  • You're deep in a third-party integration that assumes Pages. Some CMS starter kits, admin panel generators, and older auth libraries still document Pages Router-first setup. Verify current library docs before assuming — many have shipped App Router equivalents since 2024–2025.
  • Your team's expertise is Pages Router and the app is small enough that Server Components wouldn't move the needle. A marketing site with a handful of static routes gets little from streaming or Server Components.
  • You rely on `getInitialProps` patterns tightly coupled to `_app.tsx`/`_document.tsx` for things like custom error boundaries across every route — this is a non-trivial rewrite, not a drop-in swap.

When to move to the App Router

  • Starting something new. There's no reason to scaffold a greenfield project on Pages Router in 2026 — create-next-app's default is App Router, and every new Next.js capability (Turbopack's dev-memory improvements, Instant Navigations, Cache Components) assumes it.
  • You're fighting waterfall data fetching or layout re-renders. Nested layouts that persist across navigation, and the ability to fetch data at the component level instead of hoisting everything into a single page-level function, solve real performance problems Pages Router has no clean answer for.
  • You need streaming SSR — dashboards or content pages with slow, non-critical sections benefit from <Suspense> boundaries that let the fast parts render immediately.

For teams that decide a migration is warranted but don't have the internal bandwidth to do it alongside a normal release cadence, this is the kind of scoped, well-understood project a web development partner like Wise Hustlers can execute as an isolated engagement rather than a rewrite that stalls other work.

Migration reality check

Next.js supports incremental adoption: you can add an app/ directory next to an existing pages/ directory and migrate route by route, with Next.js routing requests to whichever directory owns that path. Official guidance on this lives at nextjs.org/docs/app/guides/migrating/app-router-migration. The rough sequence that works in practice:

1. Add app/ alongside pages/; both can coexist.

2. Migrate shared UI (_app.tsx, _document.tsx) into a root app/layout.tsx.

3. Move routes leaf-first — start with pages that have no shared layout dependencies.

4. Convert data fetching from getServerSideProps/getStaticProps to async Server Components.

5. Audit for client-only code (browser APIs, useState, event handlers) and mark those components "use client".

6. Remove the old route from pages/ once its app/ equivalent is verified in production.

Budget real time for step 4 and step 5 — they're where most migration bugs live, not the routing itself.

FAQ

Is the Next.js Pages Router deprecated in 2026?

No. Vercel has stated directly, and backed it up with concurrent security patches to both the current App Router-era release and the last Pages-first major, that Pages Router continues to receive bug fixes and security updates. There's no announced removal date.

Should I start a new Next.js project with Pages Router or App Router?

App Router. It's the create-next-app default, and all new framework investment — Turbopack defaults, Cache Components, Instant Navigations — targets it.

Can I use App Router and Pages Router in the same Next.js app?

Yes, this is an officially supported pattern. Next.js routes requests based on which directory (app/ or pages/) contains a matching route, so you can migrate incrementally rather than as one big rewrite.

What breaks if I migrate from Pages Router to App Router?

Nothing breaks automatically, but expect to rework data fetching (getServerSideProps/getStaticProps → async Server Components), re-audit which components need "use client", and rebuild any custom logic in _app.tsx/_document.tsx as app/layout.tsx. Route matching and most component code otherwise carries over.

Sources