The App Router is now Next.js's current stable router, but the Pages Router is still supported. This comparison lays out what actually changes between the two models so teams can decide whether a migration is worth the effort.
The Next.js Pages Router and the App Router both build React applications, but they ask developers to think about structure, rendering, and data differently. The Pages Router grew up around a file-per-route convention where every file in the pages directory becomes a page, and each page decides how and when it renders. The App Router shifts the emphasis to nested layouts, colocated files, and a component model where the rendering mode is a property of each component rather than each page.
The two models also use different vocabularies. Concepts like layout, metadata, and loading states have dedicated, first-class files in the App Router, whereas in the Pages Router they were often assembled from shared components and team-specific conventions. That normalization is part of why the App Router feels more opinionated: decisions that used to be local and inconsistent now have one expected place to live.
The App Router is the current stable router and the direction of the framework, while the Pages Router remains supported for existing projects. That means the practical question for most teams is not which router a brand-new project should start with, but whether and when an existing project should migrate.
The most visible change between the two routers is file structure. In the Pages Router, each file under pages becomes a route, and every page tends to own its own layout logic. Shared chrome like headers and footers often ends up duplicated across pages or squeezed into an app-level file that has no real sense of hierarchy.
In the App Router, routes live under an app directory and a folder can carry several role-based files: page, layout, loading, error, and not-found. Layouts wrap nested routes and persist across navigation, so the shell of the site is rendered once and only the changing part re-renders. For large sites that is a meaningful structural improvement, because it removes a whole class of layout duplication and flicker problems.
The role-based files also give every route a more granular set of UI states. A loading file can render a skeleton while a route prepares its data, an error file can contain the failed route instead of letting the whole page crash, and a not-found file handles missing resources with purpose. Teams that wire these files well end up writing less ad hoc error and loading logic by hand.
The App Router is built around React Server Components, which means components render on the server by default and you opt into client interactivity with a use client directive. In the Pages Router, nearly every component ships to the browser, which pushes far more JavaScript into the client bundle.
This distinction reshapes how teams decide what belongs where. A page that mostly renders content can stay entirely on the server, and only the genuinely interactive parts of the UI need to become client components. The result is a smaller client bundle, because the browser only downloads the code it actually needs to run.
It also changes day-to-day component habits. Developers start to think in two buckets: components that present content and components that react to user input. The presentation-first components get simpler, and the interactive ones get a clearer, smaller interface for receiving data through props.
Closely related is how the App Router handles slow work. With the Pages Router, a page typically waits for all of its data before anything reaches the browser, which means one slow query delays the entire response.
The App Router encourages streaming instead. Because server components can await their own data, the shell and the fast sections render first while slower sections reveal themselves through loading and Suspense boundaries. Users see meaningful content sooner, which is often more important than the total render time.
For most applications the switch is visible to users before developers feel it: navigation no longer waits on a blank page while a whole route assembles. Instead, the parts that are ready appear immediately and the slower regions fill in, which matches how people actually consume a long page.
The two routers also fetch and cache data differently. The Pages Router offers getServerSideProps and getStaticProps as special page exports, which are convenient but couple data fetching to the page lifecycle. In the App Router, fetching happens inside components with plain async functions, and caching is controlled per request, per fetch, or at the component level.
That flexibility is powerful, but it is also the most common source of migration surprises. Data that was cached automatically under one model may behave differently under the other, so caching behavior should be validated against production-like traffic rather than assumed to carry over.
The right way to prepare is an inventory before any code changes: which pages rely on request-time data, which were pre-rendered, and where third-party calls happen. That list becomes the migration's caching map, and it prevents the classic outcome of a site that looks identical but behaves differently under load.
If your project is new or early in its life, the App Router is the default choice and the direction the ecosystem is moving. If you are maintaining an established Pages Router application, the decision to migrate should be driven by concrete problems: layout logic, page performance, streaming needs, or a shrinking supply of Pages Router conventions in community resources.
Migration works best as an incremental exercise rather than a rewrite. Because both routers can coexist during a transition in the same application, a team can convert route by route, compare behavior, and keep shipping. Plan the layout tree first, map data fetching and caching expectations, and treat metadata and redirects as first-class work rather than an afterthought.
It is equally valid to decide not to migrate. A small site with a working Pages Router codebase and no pain points will absorb the effort without meaningful gain, and deferring a migration for a quarter or two costs little. The move earns its keep when the new capabilities fix problems the team can point to today.
Neither router is wrong, but they ask different questions. Write down the specific problems you want the App Router to solve before migrating, then let each route prove the migration works instead of moving everything at once.

Yes. It remains a supported part of Next.js, and existing Pages Router applications will not stop working. The App Router is the current stable router and where new features are being invested, so new projects are normally best started with the App Router.
They can, which is exactly what makes incremental migration practical. A team can convert one route at a time, verify behavior and performance, and remove Pages Router code gradually.
The most common surprises are differences in data fetching and caching behavior, plus layout and metadata structure. Because those differences are subtle and can depend on traffic patterns, a migration should include performance and caching tests, not just a visual comparison.
Need help building a more effective digital product or AI workflow? Explore our Web Development solutions built for faster execution and measurable business impact.
