Software Engineer | 46 questions | 2026
Next.js Interview Questions and Answers
Next.js interview questions for freshers 20
Q1FresherMost askedAnswerHideWhat is the difference between the App Router and the Pages Router in Next.js?
The Pages Router (pages/) is the original file-based router. The App Router (app/) is the newer one, built on React Server Components. It is the best choice for new projects. Both can coexist during a migration.
| Pages Router | App Router | |
|---|---|---|
| Folder | pages/ | app/ |
| Components | Client-rendered (hydrated) by default | Server Components by default |
| Data fetching | getStaticProps, getServerSideProps | async components and fetch / direct DB calls |
| Layouts | _app.tsx / _document.tsx | Nested layout.tsx, preserved across navigation |
| Special files | none | loading.tsx, error.tsx, not-found.tsx, route.ts |
| Streaming | Limited | Built in with Suspense |
| Metadata | next/head | metadata / generateMetadata |
Main benefit of the App Router: less JavaScript goes to the browser, because server components never send their code. Each route segment can also stream on its own. A route lives in a folder whose page.tsx makes it public.
What they are checking: Whether you know the mental-model shift to server-first rendering
Q2FresherMost askedAnswerHideWhat is the difference between Server Components and Client Components in Next.js?
In the App Router every component is a Server Component unless the file starts with the "use client" directive.
| Server Component | Client Component | |
|---|---|---|
| Runs | On the server only (build or request time) | Server for first HTML, then hydrated in the browser |
| JS sent to browser | None for the component itself | Yes |
| Can use | async/await, DB, secrets, fs | useState, useEffect, event handlers, browser APIs |
| Cannot use | Hooks like useState, onClick | Server-only code and secrets |
// app/page.tsx (server component)
import Counter from "./Counter";
export default async function Page() {
const res = await fetch("https://example.com/api/items");
const items: { id: number; name: string }[] = await res.json();
return (
<main>
<ul>{items.map((i) => <li key={i.id}>{i.name}</li>)}</ul>
<Counter />
</main>
);
}
// app/Counter.tsx
"use client";
import { useState } from "react";
export default function Counter() {
const [n, setN] = useState(0);
return <button onClick={() => setN(n + 1)}>{n}</button>;
}
Default to server components and push "use client" down to the small interactive leaves.
What they are checking: Whether you can decide which side a component belongs on
Q3FresherMost askedAnswerHideExplain SSR, SSG and ISR in Next.js. When would you use each?
- SSG (static site generation): HTML is built once at build time and served from a CDN. Fastest and cheapest. Use for content that rarely changes (docs, marketing pages).
- SSR (server-side rendering): HTML is generated on every request. Use for per-user or always-fresh data (dashboards, search results).
- ISR (incremental static regeneration): a static page is served, then regenerated in the background after a time window or on demand. Use for large content sites where pages change occasionally (blogs, product pages).
In the App Router you do not choose with special functions. The mode follows what the route uses:
// ISR: regenerate at most every 60 seconds
export const revalidate = 60;
export default async function Page() {
const res = await fetch("https://example.com/api/posts");
const posts: { id: number; title: string }[] = await res.json();
return <ul>{posts.map((p) => <li key={p.id}>{p.title}</li>)}</ul>;
}
Using request-time APIs such as cookies(), headers() or searchParams (or export const dynamic = "force-dynamic") makes the route dynamic (SSR). Static is the default when nothing forces dynamic rendering.
What they are checking: Whether you can map rendering strategies to real content types
Q4FresherMost askedAnswerHideHow do you fetch data in the Next.js App Router?
In a Server Component you make the component async and fetch directly. No useEffect, no API route needed for your own data.
// app/products/page.tsx
interface Product { id: number; name: string }
async function getProducts(): Promise<Product[]> {
const res = await fetch("https://example.com/api/products", {
next: { revalidate: 300 },
});
if (!res.ok) throw new Error("Failed to load products");
return res.json();
}
export default async function Page() {
const products = await getProducts();
return <ul>{products.map((p) => <li key={p.id}>{p.name}</li>)}</ul>;
}
- You can also call a database or ORM directly, since this code never reaches the browser.
- Fire independent requests in parallel with
Promise.allto avoid waterfalls. - Throwing triggers the nearest
error.tsx; callingnotFound()triggersnot-found.tsx. - For needs in the browser (polling, mutations, refetch by the user), use a Client Component with SWR or TanStack Query. For mutations, you can also use a Server Action.
What they are checking: Whether you fetch on the server first and avoid needless client fetching
Q5FresherMost askedFree with sign-inAnswerHideWhat are Route Handlers in Next.js, and when would you use them instead of Server Actions?
Route Handlers create HTTP endpoints in the App Router. You use a route.ts file that exports functions named after HTTP methods. They replace Pages Router pages/api.
Q6FresherMost askedFree with sign-inAnswerHideHow do dynamic routes work in the App Router? Explain [id], [...slug] and [[...slug]].
Wrap a folder name in square brackets to make a URL segment dynamic.
Q7FresherMost askedFree with sign-inAnswerHideHow do you handle metadata and SEO in the Next.js App Router?
Export a static metadata object or an async generateMetadata function from a layout.tsx or page.tsx. Next renders the tags on the server.
Q8FresherMost askedFree with sign-inAnswerHideHow does next/image optimise images, and what props do you have to set?
next/image serves resized images in modern formats (WebP or AVIF where supported). It loads them only when needed, and keeps space for them to avoid layout shift (CLS).
Q9FresherMost askedFree with sign-inAnswerHideWhat are layout.tsx, loading.tsx, error.tsx and not-found.tsx used for?
They are special files in the App Router. They give each route segment shared UI and states with no extra setup.
Q10FresherMost askedFree with sign-inAnswerHideHow do environment variables work in Next.js? What does NEXT_PUBLIC_ do?
Next loads variables from .env, .env.local, .env.development and .env.production (with .env.local for secrets, never committed).
Q11FresherMost askedFree with sign-inAnswerHideWhat are the ways to deploy a Next.js application?
- Vercel: zero-config, supports all features (ISR, middleware, image optimisation, edge).
- Node.js server:
next buildthennext starton a VM, container or PaaS. Supports every feature. - Docker: build an image, ideally using
output: "standalone"for a small runtime image. - Static export:
output: "export"...
Q12FresherMost askedFree with sign-inAnswerHideWhat is hydration in React and Next.js?
Hydration is the step where React attaches event handlers and state to HTML that the server already rendered. The user sees content immediately from the HTML, and the page becomes interactive once the JavaScript loads and hydrates.
Q13FresherMost askedFree with sign-inAnswerHideHow did data fetching work in the Pages Router (getStaticProps, getServerSideProps, getStaticPaths)?
In the Pages Router, page-level functions run on the server and pass props to the page component.
Q14FresherMost askedFree with sign-inAnswerHideWhat makes a Next.js route dynamically rendered instead of static?
A route is static by default. It switches to dynamic rendering (per request) when it uses something only known at request time.
Q15FresherMost askedFree with sign-inAnswerHideHow do next/font and next/script improve performance?
next/font downloads font files at build time and serves them from your own site (Google fonts or local). So there are no extra requests to a font CDN at runtime. It applies size-adjust fallbacks to avoid layout shift.
Q16FresherMost askedFree with sign-inAnswerHideHow does navigation work in Next.js? Explain the Link component, prefetching and useRouter.
next/link renders an <a> and does client-side navigation: it fetches only the needed RSC payload and swaps the page without a full reload.
Q17FresherMost askedFree with sign-inAnswerHideHow do redirects, rewrites and custom headers work in next.config?
All three are async functions in next.config that return rules.
Q18FresherMost askedFree with sign-inAnswerHideHow do you handle styling in Next.js, and what are the limits with Server Components?
Common options:
Q19FresherFree with sign-inAnswerHideWhat is Turbopack, and how does it differ from webpack in Next.js?
Turbopack is Next.js's Rust-based bundler, designed to be faster than webpack through incremental computation: it recomputes only what changed. In Next 16 it is the default bundler for development and production builds. Webpack is still available with an opt-in flag.
Q20FresherFree with sign-inAnswerHideHow do you test a Next.js application?
Use a pyramid, adapted to server and client code.
Next.js interview questions for experienced 14
Q21ExperiencedMost askedAnswerHideHow does caching work in Next.js 15 and 16? What changed from Next 14?
Next 14 cached fetch results and GET route handlers by default, which surprised many teams. Since Next 15, fetch requests and GET route handlers are not cached by default, and you opt in.
The caching layers worth knowing:
- Request memoization: identical
fetchcalls during one render are de-duplicated. - Data cache: persisted
fetchresults (opt in withnext: { revalidate: n },cache: "force-cache"or tags). - Full route cache: the rendered HTML and RSC payload of static routes.
- Router cache (client): visited segments kept in the browser. In Next 15, page segments are no longer reused by default, so navigations are fresher.
Next 16 adds an opt-in model called Cache Components. You mark code with the "use cache" directive and control how long it lives with cache life profiles, instead of route-level flags. Dynamic data inside static shells is streamed with Suspense.
export default async function Page() {
const res = await fetch("https://example.com/api/rates", {
next: { revalidate: 3600, tags: ["rates"] },
});
const rates: Record<string, number> = await res.json();
return <pre>{JSON.stringify(rates)}</pre>;
}
Tags let you clear the cache later with revalidateTag (in Next 16 it also takes a cache life profile as a second argument). Always check the docs for your exact version, since this area changes quickly.
What they are checking: Whether you know caching is opt-in now and understand the layers
Q22ExperiencedMost askedAnswerHideWhere should you store a JWT in a web app: localStorage or an HttpOnly cookie?
Prefer an HttpOnly, Secure, SameSite cookie. Any JavaScript on the page can read localStorage. So one XSS bug (or a bad npm package) lets an attacker steal the token.
| localStorage | HttpOnly cookie | |
|---|---|---|
| Readable by JS | Yes (XSS can steal it) | No |
| Sent automatically | No, you add the header | Yes, with every request to the domain |
| CSRF risk | None | Yes, so use SameSite and CSRF protection |
| Works with server components | No, the server never sees it | Yes, readable via cookies() |
// app/api/login/route.ts
import { NextResponse } from "next/server";
export async function POST() {
const token = "signed.jwt.value"; // issued after verifying credentials
const res = NextResponse.json({ ok: true });
res.cookies.set("session", token, {
httpOnly: true,
secure: true,
sameSite: "lax",
path: "/",
maxAge: 60 * 60 * 24 * 7,
});
return res;
}
Also keep access tokens short-lived and use a refresh token. Check the signature on the server for every request. Set a strict Content Security Policy. For SSR apps, cookies are the natural choice since the server can read them during rendering.
What they are checking: Whether you understand the XSS versus CSRF choice, and pick cookies for SSR
Q23ExperiencedMost askedAnswerHideHow do you revalidate cached data: time-based versus on-demand?
Time-based: the data is considered fresh for N seconds, then refreshed on a later request (stale-while-revalidate).
// route-level
export const revalidate = 60;
// or per fetch
// fetch(url, { next: { revalidate: 60 } })
On-demand: you invalidate immediately when something changes, for example from a Server Action or a webhook route.
// app/actions.ts
"use server";
import { revalidatePath, revalidateTag } from "next/cache";
export async function publishPost() {
// ... write to the database
revalidateTag("posts", "max"); // tag-based; Next 16 takes a cache life profile as 2nd argument
revalidatePath("/blog"); // or a specific route
}
Choose time-based when a delay is fine (price lists, blogs). Choose on-demand when users expect to see their own change at once (admin edits, CMS publish webhooks). Combine both: a long revalidate as a safety net plus on-demand invalidation for freshness. Tags are better than paths when many pages depend on the same data.
What they are checking: Whether you can keep data fresh without turning off caching
Q24ExperiencedMost askedFree with sign-inAnswerHideWhat are Server Actions, and what should you watch out for when using them?
Server Actions are async functions that run on the server and can be called from forms or client code. They are marked with "use server". Next creates a POST endpoint for each one automatically.
Q25ExperiencedMost askedFree with sign-inAnswerHideWhat is middleware in Next.js and what is it good for? What changed in Next 16?
Middleware runs before a request reaches a route. It can redirect, rewrite, set headers and cookies, or short-circuit with a response. It runs for the paths you match.
Q26ExperiencedMost askedFree with sign-inAnswerHideWhat is generateStaticParams and how does it relate to dynamic routes?
generateStaticParams tells Next which dynamic route values to pre-render at build time. It replaces getStaticPaths from the Pages Router.
Q27ExperiencedMost askedFree with sign-inAnswerHideWhat is streaming in Next.js, and how do Suspense boundaries help?
Streaming sends the page's HTML in chunks as each part becomes ready, instead of waiting for the slowest query. The user sees the shell immediately and slow sections fill in later.
Q28ExperiencedMost askedFree with sign-inAnswerHideWhen would you fetch data on the client (SWR or TanStack Query) instead of in a Server Component?
Use the server by default. Fetch on the client when the data depends on the browser or changes while the user is on the page.
Q29ExperiencedMost askedFree with sign-inAnswerHideWhat are route groups, parallel routes and intercepting routes in the App Router?
They are folder conventions that shape routing without changing URLs in unusual ways.
Q30ExperiencedMost askedFree with sign-inAnswerHideServer Components cannot use hooks or context. How do you provide shared client state such as a theme or a query client?
Create a small Client Component that wraps the provider and shows children. Then use it in the (server) root layout. Server components passed as children stay server components.
Q31ExperiencedMost askedFree with sign-inAnswerHideWhat is the difference between the Edge runtime and the Node.js runtime in Next.js?
You can choose the runtime per route or middleware.
Q32ExperiencedMost askedFree with sign-inAnswerHideHow do you think about CSRF, XSS and security headers in a Next.js app?
- XSS: React escapes values by default. The risks are
dangerouslySetInnerHTML, unsanitised markdown or HTML from users, and unsafe URLs (javascript:). Sanitise with a library such as DOMPurify and set a Content Security Policy. - CSRF: cookie-based auth is exposed to cross-site requests. Use
SameSite=Laxor...
Q33ExperiencedMost askedFree with sign-inAnswerHideWhat new React 19 features matter for Next.js apps (use, useActionState, useFormStatus, useOptimistic)?
The App Router uses React 19, so these are available:
Q34ExperiencedMost askedFree with sign-inAnswerHideHow do you use TanStack Query with the Next.js App Router, so the server loads the data first and the client reuses it?
Prefetch the query in a Server Component, dehydrate the cache, and pass it to a client-side provider with HydrationBoundary. The client component then reads the same query key and gets the data instantly, without a second request.
Scenario based Next.js interview questions 12
Q35ExperiencedMost askedScenarioAnswerHideA Next.js page has a very high Time To First Byte. How do you investigate and fix it?
Find where the time goes before changing anything.
- Check whether the route is rendered dynamically on every request when it could be static or cached. Look for
cookies(),headers(),searchParamsorcache: "no-store"forcing dynamic rendering. - Measure the server: log timing around each fetch and database call, or use OpenTelemetry. Look for slow queries, missing indexes and N+1 patterns.
- Remove request waterfalls: start independent fetches together with
Promise.all. - Cache what can be cached:
revalidate, tags, or"use cache"in Next 16; a CDN in front for public pages. - Stream: wrap slow, non-critical sections in Suspense so the shell is sent immediately.
- Reduce work in middleware and avoid heavy computation on the request path.
- Check geography: server and database should be in the same region, and users far away should hit a CDN.
- Check cold starts and memory limits on serverless platforms.
const [user, posts] = await Promise.all([getUser(), getPosts()]); // parallel, not sequential
Verify with real field data (Core Web Vitals, server timing headers), not only local runs.
What they are checking: Whether you follow a measurement-driven approach and know Next-specific causes
Q36ExperiencedMost askedScenarioAnswerHideYou updated content in the database, but the Next.js site still shows the old version. What could be wrong?
This is a caching question. Walk the layers from server to browser.
- Static or ISR page: the page was generated earlier and
revalidatehas not passed. Fix with on-demand revalidation (revalidatePathorrevalidateTag) after writes, or lower the interval. - Data cache: a
fetchwithforce-cacheor a longrevalidate. Use tags and invalidate them, orcache: "no-store"for truly live data. - Full route cache and generateStaticParams: new slugs need
dynamicParamstrue or a rebuild. - Router cache in the browser: soft navigation may show a previous payload. Call
router.refresh()after a mutation, or use Server Actions which refresh automatically. - CDN or reverse proxy cache (Cloudflare, nginx): check
Cache-Controland purge. Verify withcurl -Iand thex-nextjs-cacheheader (HIT, MISS, STALE). - Multiple instances with separate in-memory caches: a revalidation reached only one server. Use a shared cache handler.
- Read-replica lag or a wrong environment variable pointing at old data.
curl -sI https://example.com/blog/post | grep -i -E "cache|age|x-nextjs"
Fix by deciding the freshness requirement per page, then invalidating explicitly on write.
What they are checking: Whether you can systematically debug stale data across caches
Q37ExperiencedMost askedScenarioAnswerHideYou see 'Hydration failed because the server-rendered HTML didn't match the client'. What causes it and how do you fix it?
Hydration attaches React to server HTML. If the first client render produces different markup than the server did, React reports a mismatch.
Common causes:
- Values that differ between server and client:
Date.now(),Math.random(),new Date().toLocaleString()(time zone and locale differ). - Reading
window,localStorageornavigatorduring render. - Invalid HTML nesting, such as a
<div>inside a<p>, which the browser repairs. - Browser extensions injecting attributes, or inconsistent conditional rendering based on the user agent.
Fixes:
"use client";
import { useEffect, useState } from "react";
export function Clock() {
const [now, setNow] = useState<string | null>(null); // same on server and first client render
useEffect(() => setNow(new Date().toLocaleTimeString()), []);
return <span>{now ?? ""}</span>;
}
- Compute browser-only values in
useEffect, so the first render matches. - Use
useIdfor ids, and pass stable data (like a server-generated timestamp) as props. - Fix invalid nesting.
- Use
suppressHydrationWarningonly for unavoidable one-off text such as a timestamp. next/dynamicwithssr: falsefor components that cannot render on the server.
What they are checking: Whether you can reason about server versus client render output
Q38ExperiencedMost askedScenarioFree with sign-inAnswerHideHow would you protect pages and data behind login in a Next.js App Router app?
Use layers, and put the real check next to the data.
Q39ExperiencedMost askedScenarioFree with sign-inAnswerHidePages of your Next.js site are not appearing in Google. How do you diagnose it?
Work from what Google sees to how the page is built.
Q40ExperiencedMost askedScenarioFree with sign-inAnswerHideThe Largest Contentful Paint on a Next.js page is poor. What would you do?
First find the LCP element in Lighthouse or Chrome DevTools (usually a hero image or a big heading). Then remove what delays it.
Q41ExperiencedMost askedScenarioFree with sign-inAnswerHideYou inherit a Pages Router app and the team wants the App Router. How do you migrate safely?
Migrate incrementally, because both routers work in the same project. If a path exists in both, app/ wins, so move one route at a time.
Q42ExperiencedMost askedScenarioFree with sign-inAnswerHideYou must self-host a Next.js app on a small VM. How would you set up the build, runtime and deploys?
Build in CI, not on the small server, and ship only the output.
Q43ExperiencedMost askedScenarioFree with sign-inAnswerHideYou have a list with 100,000 items to show. How would you design pagination and rendering in Next.js?
Never render them all. Paginate or stream, and let the database do the work.
Q44ExperiencedMost askedScenarioFree with sign-inAnswerHideHow would you build a multilingual (i18n) or multi-tenant site in the App Router?
Put the variable part in a dynamic top-level segment and resolve it early.
Q45ExperiencedMost askedScenarioFree with sign-inAnswerHideYour public Next.js site is being scraped heavily and your server cost is rising. What would you do?
Reduce the cost per request first, then restrict abusers, without blocking real users or search engines.
Q46ExperiencedMost askedScenarioFree with sign-inAnswerHideA Next.js build runs out of memory or is very slow on your small server. How do you fix the deployment?
Stop building on the production machine, and shrink the build.