100+ Powerful Next JS Interview Questions and Answers (2026)

If you’re searching for next js interview questions and answers, you’re probably doing one of two things: trying to break into a Next.js role fast, or leveling up for a senior interview where App Router details actually matter. This guide is built like a real study sheet-not a blog full of theory. You’ll find next js interview questions and answers that reflect what teams ship in production today: Server vs Client Components boundaries, caching and revalidation, Route Handlers, Server Actions, middleware tradeoffs, streaming with Suspense, and modern routing patterns like parallel and intercepting routes for deep-linkable modals.

Each question is written the way interviewers evaluate: a crisp short answer, deeper bullets, a common wrong answer, and a harder follow-up-so you can explain not just what Next.js does, but why you’d choose one approach over another.

Next.js interview questions and answers featured image with developer and code on laptop

Table of Contents

Quick Cheat Sheet for Next JS Interview Questions

SSR vs SSG vs ISR vs CSR (interview-ready table)

Mode What it means Best for Pros Cons App Router “how”
SSR Render per request auth dashboards, truly dynamic pages always fresh, SEO can be slower + costly Server Components + dynamic data
SSG Render at build marketing, docs fastest TTFB stale until rebuild static segments, no request data
ISR Static + background refresh blogs, catalogs fast + can update invalidation strategy required revalidate, tags, on-demand revalidate
CSR Fetch in browser highly interactive tools rich UX slower first load, hydration Client Components + client fetching

App Router mental model: Server vs Client Components

Rules of thumb:

  • Default = Server Component (fast initial render, minimal JS).
  • Use Client Components only for:
    • hooks (useState, useEffect), event handlers, browser APIs (window)
    • client-only libraries (charts, editors)
  • Keep boundaries Server parent → Client leaf so most code stays server-rendered.

Gotcha #1 (Import direction): Client Components can’t import Server Components. Put server components above and pass props down.

Caching defaults + #1 caching gotcha (simple + accurate)

Default: In App Router, fetch requests are not cached by default. Cache explicitly with cache: 'force-cache' or time-based revalidation. (Next.js)

Your #1 caching gotcha: you invalidate the wrong layer (data vs route output vs client router cache), so the UI stays stale even though the DB updated.

Practical rule you can say out loud:

  • Cache shared reads with tags; invalidate with revalidateTag() after writes.
  • For page output, invalidate with revalidatePath() when a specific route must refresh.

Gotcha #2 (Dev surprise): In dev, the HMR cache can make “uncached” fetch feel stale until a full navigation/reload. (Next.js)

Comparison table: Next.js caching layers (what interviewers actually want)

Next.js documents multiple caches (and how they interact). (Next.js)

Layer What it caches Symptom Fix
Data Cache results of server fetch with caching stale data across pages use tags + revalidateTag, or revalidate time
Full Route Cache rendered route output whole page stays stale make route dynamic or invalidate path
Router Cache client navigation payload back/forward shows old UI refresh/revalidate strategy; avoid over-prefetch

Comparison table: App Router “special files” (know these cold)

File Purpose Key detail interviewers test
page.tsx route UI page renders for that segment (Next.js)
layout.tsx shared UI layouts preserve state across navigation (Next.js)
template.tsx like layout but resets templates reset children state (unique key) (Next.js)
loading.tsx instant loading UI built on Suspense + streaming (Next.js)
error.tsx error boundary UI must be a Client Component (Next.js)
not-found.tsx 404 UI for segment used when notFound() is triggered (Next.js)
route.ts Route Handler endpoint Web Request/Response, app-only (Next.js)

 

Most asked in 2026 interviews

If you’re short on time, these are the 12 topics that show up constantly:

  1. Server vs Client Components boundaries
  2. layout vs template and state persistence
  3. loading.tsx vs Suspense boundaries
  4. Route Handlers vs API Routes (Pages)
  5. Caching layers + why data is stale
  6. revalidatePath vs revalidateTag
  7. Parallel Routes + Intercepting Routes (deep-linkable modals)
  8. Middleware and edge/runtime tradeoffs
  9. Server Actions (forms, mutations, constraints)
  10. Server Actions security: same-origin + allowed origins config
  11. Hydration debugging
  12. Performance: streaming + bundle size + images

Debugging checklists

Hydration mismatch checklist (5 minutes)

  1. Find the first Client Component boundary involved ('use client').
  2. Remove non-determinism: Date, Math.random, locale formatting.
  3. Don’t branch on window/document during render; move to useEffect.
  4. Ensure server and client render the same initial markup.
  5. Only use suppressHydrationWarning as a last resort.

Gotcha #3: suppressHydrationWarning hides symptoms; it doesn’t fix logic.

Stale data / caching surprise checklist

  1. Identify: stale data vs stale page output vs stale client navigation. (Next.js)
  2. Confirm your fetch options (cache, next.revalidate, tags). (Next.js)
  3. After mutations, call revalidateTag() (tagged data) or revalidatePath() (route output).
  4. Check whether the route became dynamic because you read request data (cookies/headers).
  5. In dev, consider the HMR caching behavior when debugging. (Next.js)

Gotcha #4: If you never added tags to the fetch, revalidateTag() won’t help.

Middleware / edge checklist

  1. Keep middleware fast: routing, redirects, token checks.
  2. Don’t import heavy Node-only libs in edge contexts.
  3. Do real authorization in server/actions/handlers (not only middleware).
  4. If a feature needs DB access, move it to Node runtime.

Next JS Interview Questions for Freshers

These next js interview questions for freshers cover the fundamentals interviewers expect.

What is Next.js, and why use it over plain React?

Short answer: Next.js is a React framework that adds routing, server rendering, and production tooling out of the box.

Deep answer:

  • File-based routing (App Router) + nested layouts
  • Server-first rendering with Server Components by default
  • Built-in primitives: next/link, next/image, Route Handlers, caching guides

Common misconception / wrong answer: “Next.js is only SSR.”
One follow-up question (harder): When is CSR still the right choice inside Next?

What is the App Router?

Short answer: App Router is Next.js’s modern routing system under app/, built around nested layouts and Server Components. (Next.js)

Deep answer:

  • Routes come from folders with page.tsx
  • Shared UI comes from layout.tsx (persists across navigation) (Next.js)
  • Special files handle loading/error/not-found per segment (Next.js)

Common misconception / wrong answer: “It’s just Pages Router with new folders.”
One follow-up question (harder): Why do layouts persisting change how you place state?

What are Server Components?

Short answer: Server Components render on the server and don’t ship their component code to the browser.

Deep answer:

  • Great for data access and secrets
  • No React client hooks (useState, useEffect)
  • Pass only serializable props to client children

Common misconception / wrong answer: “Server Components = SSR.”
One follow-up question (harder): What makes a route effectively “dynamic”?

What does 'use client' do?

Short answer: It marks a file as a Client Component so you can use hooks, event handlers, and browser APIs.

Deep answer:

  • Creates a client boundary; minimize it for performance
  • Client components can’t import server-only modules
  • Best practice: client leaf components only

Common misconception / wrong answer: “It makes the whole app client-side.”
One follow-up question (harder): How do you refactor a large client layout into server + client leaves?

'use client'
import { useState } from 'react'
export function Counter() {
  const [n, setN] = useState(0)
  return <button onClick={() => setN(n + 1)}>{n}</button>
}

What are page.tsx and layout.tsx?

Short answer: page.tsx defines a route; layout.tsx defines shared UI that persists across pages in that segment.

Deep answer:

  • Layouts preserve state and don’t rerender on navigation
  • Great for navbars, shells, auth wrappers
  • Nest layouts for route hierarchies

Common misconception / wrong answer: “Layouts rerender every time.”
One follow-up question (harder): When would you use template.tsx instead?

What are loading.tsx, error.tsx, and not-found.tsx?

Short answer: They’re route-segment UI conventions for loading, errors, and not-found states.

Deep answer:

  • loading.tsx: instant loading UI built on Suspense/streaming
  • error.tsx: error boundary; must be Client Component
  • not-found.tsx: used when notFound() is triggered

Common misconception / wrong answer:loading.tsx replaces Suspense.”
One follow-up question (harder): Where do you place Suspense boundaries vs segment loading.tsx?

What is a Route Handler?

Short answer: A Route Handler is an endpoint in app/**/route.ts using Web Request/Response.

Deep answer:

  • App Router-only; “equivalent of Pages API Routes”
  • Supports HTTP methods: GET/POST/PUT/PATCH/DELETE, etc.
  • Good for webhooks, BFF endpoints, lightweight APIs

Common misconception / wrong answer: “You must use pages/api.”
One follow-up question (harder): When should APIs live outside Next.js entirely?

// app/api/health/route.ts
export async function GET() {
  return Response.json({ ok: true })
}

How do you do dynamic routing in App Router?

Short answer: Use brackets like app/products/[id]/page.tsx.

Deep answer:

  • params provides route params
  • Catch-all [...] and optional catch-all [[...]]
  • Pre-generate with generateStaticParams when appropriate

Common misconception / wrong answer: “Dynamic routes are always SSR.”
One follow-up question (harder): How do you pre-render only popular routes without exploding build time?

What is generateMetadata used for?

Short answer: It generates per-route metadata (title, description, OG tags) server-side.

Deep answer:

  • Useful for SEO on dynamic content
  • Avoid double-fetching; share data where possible
  • Make sure caching behavior matches your data freshness needs

Common misconception / wrong answer: “SEO must be in _document.”
One follow-up question (harder): How do you avoid fetching the same data in both generateMetadata and the page?

How does Next.js handle images?

Short answer: next/image optimizes images with responsive sizing and lazy loading.

Deep answer:

  • Prevents shipping oversized images
  • Helps LCP when used with correct sizing
  • Still requires good source images and correct layout usage

Common misconception / wrong answer: “It automatically fixes all image performance issues.”
One follow-up question (harder): What mistakes can make images hurt LCP?

How do environment variables work?

Short answer: Only NEXT_PUBLIC_* env vars are exposed to the browser; others stay server-side.

Deep answer:

  • Keep secrets server-only (no NEXT_PUBLIC_)
  • Read env vars in Server Components/Route Handlers
  • Validate env at startup to fail fast

Common misconception / wrong answer: “All env vars are available everywhere.”
One follow-up question (harder): How do you enforce env validation in CI?

What is hydration?

Short answer: Hydration is React attaching event handlers to server-rendered HTML in the browser.

Deep answer:

  • Mismatches happen when server and client render different initial markup
  • Usually caused by non-deterministic values
  • Fix by moving browser-only logic into effects or client-only components

Common misconception / wrong answer: “Hydration warnings are harmless.”
One follow-up question (harder): Give a step-by-step debugging plan for hydration mismatches.

Gotcha #5: new Date() in render can mismatch between server and client.

What is streaming?

Short answer: Streaming sends HTML in chunks as parts become ready, improving perceived performance.

Deep answer:

  • Built on React Suspense patterns
  • Allows fast shell + slower widgets
  • Works especially well for dashboards and feeds

Common misconception / wrong answer: “Streaming means WebSockets.”
One follow-up question (harder): Where would you place boundaries on a 6-widget dashboard?

What is middleware?

Short answer: Middleware runs before the request completes, often at the edge, to rewrite/redirect/gate routes.

Deep answer:

  • Great for auth gating and locale redirects
  • Keep it lightweight (no heavy DB logic)
  • Use matcher to scope it

Common misconception / wrong answer: “Middleware replaces server authorization.”
One follow-up question (harder): What should middleware do vs what should Server Actions do?

Redirect vs rewrite – what’s the difference?

Short answer: Redirect changes the URL; rewrite serves different content without changing the URL.

Deep answer:

  • Redirect: SEO/canonical changes
  • Rewrite: locale routing, vanity URLs, A/B routing
  • Both can affect caching and analytics

Common misconception / wrong answer: “They’re basically the same.”
One follow-up question (harder): How can rewrites accidentally cause cache confusion?

Why use next/link?

Short answer: It enables client-side navigation and prefetching for faster route transitions.

Deep answer:

  • Preserves layouts across navigation
  • Prefetch can boost UX, but can overfetch
  • Use plain <a> for external links

Common misconception / wrong answer: “Prefetch is always good.”
One follow-up question (harder): How do you avoid bandwidth spikes on large link grids?

What is a Route Group?

Short answer: (group) folders organize code without affecting the URL path. (Next.js)

Deep answer:

  • Separate (marketing) vs (app) without changing URLs
  • Useful for applying different layouts by group
  • Great for team ownership boundaries

Common misconception / wrong answer: “Route groups add to the URL.”
One follow-up question (harder): How do route groups help isolate auth layouts?

What is template.tsx used for?

Short answer: It wraps pages like a layout but resets child state on navigation.

Deep answer:

  • Layout persists; template resets
  • Useful for animations or resetting form state
  • Use sparingly; state resets can be surprising

Common misconception / wrong answer: “Template is just another name for layout.”
One follow-up question (harder): Give a case where template is harmful for UX.

What is notFound()?

Short answer: It triggers the route segment not-found.tsx UI.

Deep answer:

  • Use for missing DB/API resources
  • Better than rendering “not found” text manually
  • Keeps routing semantics consistent

Common misconception / wrong answer: “Return null for missing data.”
One follow-up question (harder): How do you handle SEO metadata for missing resources?

How do you add global styles in App Router?

Short answer: Import global CSS in the root app/layout.tsx.

Deep answer:

  • Root layout is the correct place for global UI and styles
  • Component styles: CSS Modules/Tailwind
  • Avoid scattering global CSS across routes

Common misconception / wrong answer: “Import global CSS anywhere.”
One follow-up question (harder): How do you manage theming cleanly?

What are Server Actions?

Short answer: Server Actions run on the server and can be invoked from forms or client interactions for mutations.

Deep answer:

  • Great for CRUD forms with less client boilerplate
  • Keep validation + auth checks on server
  • Pair with revalidation after writes

Common misconception / wrong answer: “Server Actions run in the browser.”
One follow-up question (harder): What are the serialization constraints and why?

// app/actions.ts
'use server'
export async function createTodo(formData: FormData) {
  const title = String(formData.get('title') ?? '')
  if (!title.trim()) throw new Error('Title required')
  // write to DB (pseudo)
}

Server Actions: what about CSRF?

Short answer: Next.js compares origin vs host for Server Actions and supports configuring allowed origins behind proxies. (Next.js)

Deep answer:

  • Same-origin by default; configure serverActions.allowedOrigins when needed
  • Still do auth + validation + rate limiting (best practice)
  • Be careful with multi-domain setups and proxies

Common misconception / wrong answer: “CSRF can’t happen because it’s POST.”
One follow-up question (harder): What’s your full mutation security checklist?

Gotcha #6: Misconfigured proxies can break origin/host checks and cause production-only failures.

How do you keep client bundles small?

Short answer: Make most components server, and push 'use client' down to leaf components.

Deep answer:

  • Avoid client root layouts unless necessary
  • Don’t ship heavy libraries unless required
  • Use dynamic imports for rarely used widgets

Common misconception / wrong answer: “Tree-shaking will handle it.”
One follow-up question (harder): How do you find which dependency inflates the bundle?

What’s a good default approach to data fetching?

Short answer: Fetch in Server Components for initial render; use client fetching only for interactive/user-specific updates.

Deep answer:

  • Server fetch: SEO + faster first meaningful render
  • Client fetch: great for live updates and UI interactions
  • Mix: server baseline + client refinement

Common misconception / wrong answer: “Client fetching is always bad.”
One follow-up question (harder): When is client fetching better for performance?

Name one performance habit you do on every Next app.

Short answer: Keep client boundaries small, and measure Core Web Vitals.

Deep answer:

  • Stream slow sections with Suspense
  • Optimize images and avoid layout shift
  • Profile bundle size and reduce client JS

Common misconception / wrong answer: “Next is fast by default; no work needed.”
One follow-up question (harder): How do you debug a slow TTFB in production?

Related preparation

Use these when interview prep crosses into React and Node fundamentals:

Next JS Interview Questions for 3–5 Years Experience

These next js interview questions for experienced developers go deeper into App Router behavior and caching.

Related reading React interview questions and answers
Related reading React Hooks interview questions and answers

Next.js App Router diagram showing route groups, parallel routes, and intercepting routes modal pattern

Explain template.tsx vs layout.tsx.

Short answer: Layouts persist and preserve state; templates reset state on navigation.

Deep answer:

  • Use layout for shells (nav/sidebar) that should stay mounted
  • Use template when you need a fresh instance each navigation
  • Templates can reset client state (good or bad depending)

Common misconception / wrong answer: “They’re identical.”
One follow-up question (harder): What bugs can template introduce in long forms?

How do Route Groups change your architecture?

Short answer: They let you reorganize routes and apply different layouts without changing URLs.

Deep answer:

  • (marketing) vs (app) separation
  • Different layouts/auth boundaries per group
  • Cleaner ownership for teams

Common misconception / wrong answer: “You need multiple Next apps.”
One follow-up question (harder): How do you avoid duplicated providers across groups?

Explain Parallel Routes with a real use case.

Short answer: Parallel Routes render multiple slots (e.g. @modal, @sidebar) inside one layout.

Deep answer:

  • Dashboards: main content + persistent panels
  • Independent loading/error UI per slot
  • Combine with Intercepting Routes for modals

Common misconception / wrong answer: “Parallel routes are just nested routes.”
One follow-up question (harder): What’s default.tsx used for in slots? (Next.js)

What are Intercepting Routes and why do they matter?

Short answer: They let you load a route “within” the current layout context (classic: deep-linkable modals).

Deep answer:

  • Modal URL is shareable
  • Refresh keeps context instead of closing modal
  • Back button closes modal instead of leaving page

Common misconception / wrong answer: “Modals must be client state only.”
One follow-up question (harder): Explain (.) vs (..) conventions.

Folder convention (explicit, interview-friendly):

app/
  gallery/
    page.tsx                 # /gallery (grid)
    [id]/
      page.tsx               # /gallery/123 (full page on hard nav)
    @modal/
      (.)[id]/
        page.tsx             # intercept /gallery/123 and render as modal
      default.tsx            # render null when modal not active

Gotcha #7: Intercepting route conventions are based on route segments, not the filesystem (slots don’t count as segments).

Route Handlers vs API Routes – when do you pick which?

Short answer: Use Route Handlers in App Router; API Routes (pages/api) are legacy for Pages Router.

Deep answer:

  • Route Handlers: Web Request/Response, app-only
  • API Routes: older pages/api model (still used in legacy apps)
  • Pick based on your router/migration stage

Common misconception / wrong answer: “Use both together.”
One follow-up question (harder): When would you build APIs outside Next (separate service)?

Comparison table: Route Handlers vs API Routes

Topic Route Handlers API Routes
Location app/**/route.ts pages/api/**
API style Web APIs (Next.js) Node req/res
Best for modern App Router apps legacy or migrations
Note equivalent to API Routes (Next.js) Pages Router-only

What are the caching defaults for fetch in App Router?

Short answer: By default, fetch is not cached; you opt into caching or revalidation per request.

Deep answer:

  • Cache: fetch(url, { cache: 'force-cache' })
  • No cache: fetch(url, { cache: 'no-store' })
  • Time-based revalidation: next: { revalidate: seconds } (common pattern)

Common misconception / wrong answer: “Fetch is cached by default like old ISR.”
One follow-up question (harder): How do different revalidate values across multiple fetches interact?

Explain revalidatePath vs revalidateTag.

Short answer: revalidatePath invalidates a route; revalidateTag invalidates all cached data requests labeled with a tag.

Deep answer:

  • Tags scale better for shared data used in many routes
  • Path invalidation is simpler for single-route refresh
  • Always call invalidation after successful mutations

Common misconception / wrong answer: “Next auto-refreshes after POST.”
One follow-up question (harder): How do you design tags for “products by category” and “product detail”?

What’s the cleanest way to handle forms in App Router?

Short answer: Use Server Actions for first-party UI mutations; use Route Handlers for HTTP APIs and integrations.

Deep answer:

  • Server Actions: <form action={action}> fits naturally with RSC
  • Route Handlers: versionable endpoints for mobile/webhooks
  • Both require auth + validation

Common misconception / wrong answer: “Everything must go through /api.”
One follow-up question (harder): When does Server Actions become a bad fit (team scale, contracts)?

// app/todos/page.tsx
import { createTodo } from './actions'
export default function Page() {
  return (
    <form action={createTodo}>
      <input name="title" />
      <button type="submit">Add</button>
    </form>
  )
}

Server Actions: what can you pass as arguments?

Short answer: Only serializable values (and FormData), not functions or complex class instances.

Deep answer:

  • Think “RPC over serialization”
  • Prefer IDs + primitives
  • Validate everything at the action entry

Common misconception / wrong answer: “You can pass a DB connection into the action.”
One follow-up question (harder): How do you handle file uploads safely?

Server Actions security: how do allowed origins work?

Short answer: Same-origin is the default; you can add safe origins via serverActions.allowedOrigins for proxy setups.

Deep answer:

  • Next compares origin vs host to prevent CSRF
  • Configure allowed origins only when you must (reverse proxies, multi-domain)
  • Still do auth, validation, and rate limits

Common misconception / wrong answer: “No CSRF protection needed ever.”
One follow-up question (harder): How do you design a secure mutation layer across actions + handlers?

What’s the best practice for error handling in App Router?

Short answer: Use segment-level error.tsx boundaries and handle expected errors explicitly.

Deep answer:

  • error.tsx catches unexpected runtime errors for a segment
  • Expected errors (validation) should return user-friendly messages
  • Smaller boundaries reduce blast radius

Common misconception / wrong answer: “One global try/catch is enough.”
One follow-up question (harder): How do you avoid leaking sensitive info in error messages?

How do you debug hydration issues fast?

Short answer: Isolate the first client boundary and remove non-determinism.

Deep answer:

  • Date, random, locale are common offenders
  • Don’t render browser-only values on server
  • Make initial server/client markup identical

Common misconception / wrong answer: “Just suppress the warning.”
One follow-up question (harder): How do you refactor a component to be deterministic?

Gotcha #8: Locale formatting differs between server and user devices; render it on one side only.

How do you reduce client bundle size in a real app?

Short answer: Make the shell server-rendered and push interactivity into small client leaves.

Deep answer:

  • Avoid 'use client' in root layouts
  • Dynamic import rarely used widgets
  • Audit heavy dependencies

Common misconception / wrong answer: “Bundle size doesn’t matter because of HTTP/2.”
One follow-up question (harder): How do you prove a dependency causes LCP regressions?

How do you structure a large app/ directory?

Short answer: Use route groups, shared components/, and server-only lib/ utilities.

Deep answer:

  • (marketing) and (app) route groups for clear boundaries
  • Co-locate route-specific code inside the segment folder
  • Keep server-only code separate to prevent accidental client bundling

Common misconception / wrong answer: “Put everything under components/.”
One follow-up question (harder): How do you enforce boundaries with lint rules?

How do you implement auth cleanly in App Router?

Short answer: Enforce auth on the server (layouts/actions/handlers) and use middleware for coarse gating.

Deep answer:

  • Middleware: redirect unauthenticated quickly
  • Server: real authorization (permissions) for every request/mutation
  • Avoid caching user-specific responses globally

Common misconception / wrong answer: “If the button is hidden, it’s secure.”
One follow-up question (harder): How do you prevent cache leakage across users?

Gotcha #9 (Auth + caching): Caching user-specific output without scoping can leak data across sessions.

How do you choose between SSR/SSG/ISR in App Router?

Short answer: Choose based on freshness needs and cost; then implement with caching/revalidation primitives.

Deep answer:

  • Marketing: static/SSG
  • Catalog: ISR + tags
  • Dashboards: dynamic SSR + server fetch + streaming

Common misconception / wrong answer: “Always SSR because it’s fresh.”
One follow-up question (harder): How do you keep 90% static and personalize 10%?

What’s the purpose of loading.tsx and how is it scoped?

Short answer: It’s a route segment-level loading UI using Suspense while the segment streams.

Deep answer:

  • Put it in the segment folder you want to cover
  • Use skeletons matching the final layout
  • Combine with finer Suspense boundaries for widgets

Common misconception / wrong answer: “One root loading.tsx covers everything.”
One follow-up question (harder): How do you design loading states per slot in parallel routes?

How do you implement a webhook endpoint?

Short answer: Use a Route Handler; validate signature; respond fast; queue heavy work.

Deep answer:

  • Route Handlers are standard HTTP endpoints
  • Validate signatures and idempotency
  • Offload long work to a background worker

Common misconception / wrong answer: “Do all processing inside the request.”
One follow-up question (harder): How do you make webhook processing idempotent?

How do you test Next.js apps effectively?

Short answer: Combine unit tests (React), integration tests (actions/handlers), and E2E for critical flows.

Deep answer:

  • Unit: component logic
  • Integration: auth + validation + revalidation
  • E2E: routing, modals, caching behavior

Common misconception / wrong answer: “Only E2E matters.”
One follow-up question (harder): How do you test revalidation deterministically?

Related reading (react testing interview questions)

How do you implement pagination without client fetching?

Short answer: Read searchParams in a Server Component and render based on the page param.

Deep answer:

  • searchParams.page drives the server render
  • Use Link for navigation
  • Cache and revalidate depending on data type

Common misconception / wrong answer: “Pagination requires client state.”
One follow-up question (harder): How do you keep pagination SEO-friendly?

What’s a common reason “stale data” happens after a mutation?

Short answer: The mutation works, but you didn’t invalidate the cached reads or route output.

Deep answer:

  • Add tags to shared fetches
  • After write: revalidateTag()/revalidatePath()
  • Confirm you’re not relying on dev HMR behavior

Common misconception / wrong answer: “React state is broken.”
One follow-up question (harder): How do you instrument cache hit/miss?

How do you implement a deep-linkable modal correctly?

Short answer: Use Parallel Routes + Intercepting Routes (URL-driven modals).

Deep answer:

  • Slot @modal renders modal UI
  • Intercept the detail route into modal slot (e.g. (.)[id])
  • Direct URL loads full page route

Common misconception / wrong answer: “Just store isOpen in state.”
One follow-up question (harder): How do you handle multiple modals (login + signup) with slots?

How do you avoid data-fetch waterfalls in Server Components?

Short answer: Fetch in parallel and place Suspense boundaries thoughtfully.

Deep answer:

  • Avoid sequential await chains when possible
  • Fetch in parent and pass results down
  • Use Suspense to isolate slow sections

Common misconception / wrong answer: “Server rendering automatically parallelizes all awaits.”
One follow-up question (harder): How do you structure a dashboard to stream independently?

Gotcha #10: Sequential awaits can quietly add hundreds of ms.

How do you prevent over-prefetching?

Short answer: Don’t prefetch massive link lists; paginate and be intentional about navigation.

Deep answer:

  • Large grids can trigger lots of prefetch work
  • Prefetch should be used where it helps conversions/UX
  • Monitor real-user bandwidth and device constraints

Common misconception / wrong answer: “Prefetch never hurts.”
One follow-up question (harder): How would you conditionally prefetch based on network?

How do you handle “expected errors” in forms?

Short answer: Return user-friendly validation errors; don’t throw for normal validation failures.

Deep answer:

  • Schema validate at action/handler entry
  • Return structured error results
  • Throw only for unexpected exceptions

Common misconception / wrong answer: “Throw errors for all failures.”
One follow-up question (harder): How do you map server errors to field-level messages?

How do you design cache tags for a catalog?

Short answer: Use coarse tags (products) plus scoped tags (product:123, category:shoes) to invalidate surgically.

Deep answer:

  • Shared list pages use category tags
  • Detail pages use product:{id} tags
  • Mutation revalidates the minimal set

Common misconception / wrong answer: “Use one tag for everything.”
One follow-up question (harder): How do you handle search results caching without tag explosion?

When would you prefer Route Handlers over Server Actions?

Short answer: For public APIs, mobile clients, webhooks, integrations, and explicit HTTP contracts.

Deep answer:

  • Actions are great for first-party UI
  • Handlers are better for multi-client contracts and versioning
  • Both still need auth/validation/observability

Common misconception / wrong answer: “Server Actions replace APIs entirely.”
One follow-up question (harder): How do you version and deprecate Route Handler endpoints?

Next JS Interview Questions for Senior Developer

These next js interview questions for senior developer roles focus on architecture, tradeoffs, and production reliability.

Design a Next.js architecture for a multi-tenant SaaS.

Short answer: Resolve tenant early, enforce authz server-side, and scope caching per tenant/user.

Deep answer:

  • Tenant resolution: subdomain/path + middleware rewrite
  • Authz in server layouts/actions/handlers (middleware only gates)
  • Cache scoping: tags per tenant; avoid shared cache for personalized output

Common misconception / wrong answer: “TenantId in URL solves isolation.”
One follow-up question (harder): How do you guarantee no cache leakage across tenants?

Where do you put authorization checks?

Short answer: Middleware for coarse routing, server/actions/handlers for enforcement, DB constraints for defense in depth.

Deep answer:

  • Middleware: fast redirect for unauthenticated
  • Actions/handlers: permissions checks on every mutation
  • DB: scoped queries or RLS when available

Common misconception / wrong answer: “Middleware alone is secure.”
One follow-up question (harder): How do you test authz rules across layers?

Edge runtime vs Node runtime: tradeoffs?

Short answer: Edge is low latency but limited; Node supports full ecosystem and DB clients.

Deep answer:

  • Edge: good for middleware, token checks
  • Node: DB, heavy libs, longer processing
  • Split “edge gate” + “node data” paths

Common misconception / wrong answer: “Edge can run anything.”
One follow-up question (harder): What breaks when you import Node-only libs into edge code?

Design caching for a high-traffic product listing.

Short answer: Cache shared reads with tags and invalidate surgically after writes.

Deep answer:

  • Tag lists by category + global products
  • Revalidate tags after product update
  • Keep personalization dynamic or scoped

Common misconception / wrong answer: “Set revalidate: 60 everywhere.”
One follow-up question (harder): How do you keep search caching from exploding cardinality?

Streaming strategy for dashboards?

Short answer: Stream the shell immediately and suspend slow widgets independently.

Deep answer:

  • One Suspense per widget
  • Parallelize data fetching
  • Provide skeletons, not spinners

Common misconception / wrong answer: “Wrap the whole page in one Suspense.”
One follow-up question (harder): How do you avoid waterfalls with multiple data sources?

import { Suspense } from 'react'

export default function Dashboard() {
  return (
    <>
      <h1>Dashboard</h1>
      <Suspense fallback={<div>Loading revenue…</div>}>
        {/* async server widget */}
        {/* @ts-expect-error Async Server Component */}
        <RevenueWidget />
      </Suspense>
    </>
  )
}

Gotcha #11: One huge boundary blocks the whole page; users perceive it as “slow SSR”.

How do you handle stale UI after mutations at scale?

Short answer: Standardize mutation wrappers + consistent tag/path invalidation.

Deep answer:

  • After write: revalidate tags or paths consistently
  • Add observability around invalidation calls
  • Use optimistic UI only where it’s safe

Common misconception / wrong answer: “Just call router.refresh() everywhere.”
One follow-up question (harder): When is router.refresh() acceptable vs a code smell?

Server Actions risks in large teams?

Short answer: You need consistent auth/validation patterns and logging, or you’ll ship insecure/inconsistent actions.

Deep answer:

  • Easy to forget authorization on one action
  • Hard to debug without consistent structured logs
  • Wrap actions with shared policy and validation

Common misconception / wrong answer: “Actions are secure by default.”
One follow-up question (harder): What’s your action wrapper API design?

How do you implement an “action wrapper” pattern?

Short answer: Centralize validation, auth, error mapping, and logging around every action.

Deep answer:

  • Validate inputs at entry (schema)
  • Enforce permission checks
  • Map errors to safe user messages and log details

Common misconception / wrong answer: “Actions are tiny; wrappers are overkill.”
One follow-up question (harder): How do you prevent sensitive data leaking into logs?

'use server'
export async function withAuth<T>(fn: () => Promise<T>) {
  // pseudo: assert session + permissions
  return await fn()
}

How do you avoid coupling UI to the data layer?

Short answer: Keep domain logic in server-only modules and expose typed functions/actions to UI.

Deep answer:

  • lib/server/* for domain services
  • UI calls domain functions, not raw DB calls everywhere
  • Client components stay presentational

Common misconception / wrong answer: “Calling DB in Server Components is always fine.”
One follow-up question (harder): How do you enforce this architecture in a monorepo?

How do you design webhook ingestion in Next.js?

Short answer: Route Handler + signature validation + fast ack + async processing.

Deep answer:

  • Route Handlers are standard endpoints
  • Make processing idempotent (event IDs)
  • Push heavy work to queues/workers

Common misconception / wrong answer: “Do everything in the request.”
One follow-up question (harder): What’s your retry strategy and how do you prevent duplicates?

How do you manage DB connections in serverless?

Short answer: Use pooling/proxies and don’t create a brand-new connection per request.

Deep answer:

  • Pooler/proxy reduces connection storms
  • Reuse clients when runtime allows
  • Monitor connection limits and latency

Common misconception / wrong answer: “New client per request is fine.”
One follow-up question (harder): What changes if part of the stack runs on edge?

How do you implement i18n routing cleanly?

Short answer: Use middleware rewrites/redirects and ensure caching varies by locale.

Deep answer:

  • Detect locale (path/cookie/header)
  • Rewrite to locale segments
  • Avoid duplicate content by canonical strategy

Common misconception / wrong answer: “Locale is only frontend.”
One follow-up question (harder): How do you prevent SEO duplicate-content issues?

How do you implement preview mode for CMS content?

Short answer: Use secure preview tokens, disable caching for previews, and keep preview out of public cache tags.

Deep answer:

  • Authenticated preview sessions
  • no-store / dynamic behavior for preview
  • Separate tags so preview doesn’t poison cache

Common misconception / wrong answer: “Preview is just a query param.”
One follow-up question (harder): How do you prevent preview data leakage?

How do you handle partial failures on a streamed page?

Short answer: Use smaller error boundaries per widget so one failure doesn’t kill the whole page.

Deep answer:

  • Segment or widget-level boundaries
  • Graceful fallback UI per widget
  • Strong logging + correlation IDs

Common misconception / wrong answer: “Root boundary is enough.”
One follow-up question (harder): How do you decide which failures should bubble up?

How do you build a public API contract in Next.js?

Short answer: Use Route Handlers, version endpoints, and share schema validation with internal actions.

Deep answer:

  • Explicit HTTP contract with handlers
  • Shared domain layer and validation
  • Deprecation plan and observability

Common misconception / wrong answer: “Use Server Actions for public APIs.”
One follow-up question (harder): How do you do API versioning without breaking clients?

What do you monitor in production?

Short answer: TTFB, cache hit rates, Core Web Vitals, error rate, and slow endpoints.

Deep answer:

  • Separate server latency from client latency
  • Track invalidation frequency (revalidate storms)
  • Alert on auth/caching regressions

Common misconception / wrong answer: “Frontend metrics are enough.”
One follow-up question (harder): What’s your incident playbook for a caching regression?

How do you prevent accidental client bundling?

Short answer: Enforce boundaries: server-only modules, lint rules, and review for 'use client' creep.

Deep answer:

  • Separate “server-safe” vs “client-only” packages
  • Avoid importing browser deps in shared server code
  • Keep providers server unless necessary

Common misconception / wrong answer: “If it builds, it’s fine.”
One follow-up question (harder): How do you detect that a server dependency got shipped to the client?

How do you handle rate limiting and abuse?

Short answer: Apply coarse limits at edge/middleware and strict limits at server endpoints for mutations.

Deep answer:

  • IP/user-based throttles
  • Protect auth and write endpoints most
  • Consider captcha/step-up auth for abuse

Common misconception / wrong answer: “Only the CDN should rate limit.”
One follow-up question (harder): How do you avoid blocking whole offices behind NAT?

What’s your security checklist for Server Actions?

Short answer: Same-origin/allowed origins config, authz checks, validation, rate limits, and safe error handling.

Deep answer:

  • Configure allowedOrigins only when needed
  • Verify permissions on every mutation
  • Validate inputs and avoid leaking sensitive info

Common misconception / wrong answer: “SameSite cookies make CSRF impossible.”
One follow-up question (harder): How do you secure mutations across both actions and handlers consistently?

How do you scale a Next.js monorepo?

Short answer: Shared packages, strict boundaries, unified patterns for actions/handlers, and incremental upgrades.

Deep answer:

  • Shared UI with server/client separation
  • Shared domain services
  • CI checks for boundary violations

Common misconception / wrong answer: “Monorepo = fewer problems.”
One follow-up question (harder): How do you avoid circular dependencies between packages?

How do you decide between GraphQL vs REST vs Server Actions?

Short answer: Actions for first-party UI mutations, REST for compatibility, GraphQL for complex multi-client querying.

Deep answer:

  • Actions: minimal client glue, great UX
  • REST: stable contracts for integrations
  • GraphQL: flexible queries across clients

Common misconception / wrong answer: “GraphQL is always better.”
One follow-up question (harder): How do you cache and secure GraphQL effectively?

How do you plan framework upgrades safely?

Short answer: Upgrade incrementally, protect critical flows with tests, and monitor runtime/caching behavior changes.

Deep answer:

  • Pin versions, upgrade in small steps
  • Integration tests for routing/auth/caching
  • Rollback plan for production

Common misconception / wrong answer: “Fix build errors and ship.”
One follow-up question (harder): What do you watch for specifically in caching changes?

How do you implement URL-driven modals in a design system?

Short answer: Provide a “slot + modal shell” pattern and keep modal content server-renderable when possible.

Deep answer:

  • Slot renders modal shell
  • Content can remain Server Component if modal shell is client
  • Back/forward behavior stays correct

Common misconception / wrong answer: “All modals must be client components.”
One follow-up question (harder): How do you support no-JS hard navigation gracefully?

What’s a common senior-level Next.js debugging story?

Short answer: Fixing “stale data” by realizing invalidation targeted the wrong cache layer.

Deep answer:

  • Data was cached with tags; dev invalidated only a path
  • Correct fix: revalidate the tag after mutations
  • Added instrumentation to prove it

Common misconception / wrong answer: “Just refresh the router.”
One follow-up question (harder): How do you design tags to prevent invalidation storms?

What’s your performance “north star” for a Next app?

Short answer: Fast TTFB + great LCP with minimal client JS.

Deep answer:

  • Server-first rendering + streaming
  • Keep client boundaries lean
  • Optimize images and avoid layout shift

Common misconception / wrong answer: “Performance is just CDN.”
One follow-up question (harder): How do you prove which change improved LCP?


Next JS Scenario-Based Interview Questions

Users report “data is stale” after a form submit. What do you check first?

Short answer: Which cache layer is serving stale content and whether invalidation runs after the mutation.

Deep answer:

  • Confirm write succeeded
  • Confirm fetch is cached (force-cache / revalidate / tags)
  • Confirm you call revalidateTag() / revalidatePath() after write

Common misconception / wrong answer: “It’s just React state.”
One follow-up question (harder): How do you log cache hit/miss in production?

A modal works, but refresh closes it and deep links don’t open it. Fix?

Short answer: Make it URL-driven with Parallel + Intercepting Routes.

Deep answer:

  • Add @modal slot with default.tsx
  • Intercept detail route into slot using (.)/(..)
  • Full page route for hard navigation remains intact

Common misconception / wrong answer: “Persist state in localStorage.”
One follow-up question (harder): How do you support multiple modals in different UI regions?

Hydration warning: “Text content does not match…” What’s your approach?

Short answer: Find the first client boundary involved and remove non-deterministic rendering.

Deep answer:

  • Look for Date, random, locale, window branching
  • Move browser-only logic to useEffect
  • Ensure consistent initial markup

Common misconception / wrong answer: “Ignore warnings.”
One follow-up question (harder): How do you write deterministic time formatting across server + client?

Middleware needs DB access but edge runtime can’t use your DB client. Now what?

Short answer: Keep middleware lightweight and move DB work to Node routes/actions.

Deep answer:

  • Middleware: validate token / redirect only
  • Node: fetch permissions and data
  • Consider caching permissions server-side

Common misconception / wrong answer: “Bundle the DB driver into middleware.”
One follow-up question (harder): How do you keep latency low without DB calls in middleware?

Build times explode because you pre-render too many dynamic pages. Fix?

Short answer: Pre-render only hot paths and rely on revalidation for the long tail.

Deep answer:

  • Limit generateStaticParams to popular routes
  • Use revalidation + tags for freshness
  • Add on-demand invalidation after writes

Common misconception / wrong answer: “SSG everything.”
One follow-up question (harder): How do you choose which paths are “hot” without guessing?

A marketing page should be static but renders dynamically. Why?

Short answer: You’re likely reading request-specific APIs (cookies/headers) or opted into dynamic behavior.

Deep answer:

  • Search for request-driven code
  • Move personalization into a separate client leaf or segment
  • Keep the core page static

Common misconception / wrong answer: “Dynamic route params force SSR.”
One follow-up question (harder): How do you keep a static page with a personalized header?

You need a public API for mobile clients. Use Server Actions?

Short answer: No-use Route Handlers for explicit HTTP contracts.

Deep answer:

  • Actions are best for first-party UI
  • Handlers are versionable and multi-client friendly
  • Add auth, rate limits, monitoring

Common misconception / wrong answer: “Actions are modern so always use them.”
One follow-up question (harder): How do you version handlers and deprecate old versions?

Page is slow in production but fast locally. Checklist?

Short answer: Separate server latency, cache behavior, and client bundle cost.

Deep answer:

  • Measure TTFB, DB latency, upstream API time
  • Confirm cache hit rate and revalidation config
  • Analyze client bundle and long tasks

Common misconception / wrong answer: “It’s always CDN.”
One follow-up question (harder): How do you isolate “server slow” vs “client slow” in 10 minutes?

After enabling prefetch, bandwidth spikes on mobile. Fix?

Short answer: Reduce prefetch pressure (pagination, fewer links, disable where not valuable).

Deep answer:

  • Avoid huge grids of Links on one page
  • Prefer pagination/infinite scroll patterns
  • Monitor real-user bandwidth

Common misconception / wrong answer: “Prefetch cannot hurt.”
One follow-up question (harder): How would you prefetch only on Wi-Fi?

error.tsx doesn’t catch a certain error. Why?

Short answer: Boundary scope may not include it, or error occurs outside render lifecycle.

Deep answer:

  • Place boundaries closer to risky segments
  • Ensure error occurs during render/async render path
  • Use explicit expected error handling for known failures

Common misconception / wrong answer: “Root error catches everything.”
One follow-up question (harder): How do you handle errors thrown by upstream data sources cleanly?

A user sees another user’s data. What happened?

Short answer: Personalized output was cached globally (cache leakage).

Deep answer:

  • Personalization should be dynamic or scoped
  • Don’t reuse shared caches for user-specific data
  • Audit tags and caching options

Common misconception / wrong answer: “Impossible in Next.”
One follow-up question (harder): What guardrails prevent this in your architecture?

A Server Action fails only behind a proxy. Why?

Short answer: Origin/host checks can fail unless allowed origins and forwarding headers are configured correctly.

Deep answer:

  • Confirm Origin and Host/forwarded host behavior
  • Configure serverActions.allowedOrigins when needed
  • Validate cookie domain and SameSite settings

Common misconception / wrong answer: “Random Next.js bug.”
One follow-up question (harder): How do you reproduce this locally with a reverse proxy?

One slow dashboard widget blocks the entire page. Fix?

Short answer: Stream widgets independently with Suspense boundaries.

Deep answer:

  • One Suspense per widget
  • Fetch in parallel
  • Skeleton fallbacks per widget

Common misconception / wrong answer: “Make whole page client-side.”
One follow-up question (harder): How do you avoid data-fetch waterfalls?

Third-party script destroys performance. What do you do?

Short answer: Defer/limit loading, audit impact, and load only on routes that need it.

Deep answer:

  • Lazy/conditional load
  • Measure long tasks and CWV impact
  • Replace or remove non-critical scripts

Common misconception / wrong answer: “Third-party scripts don’t affect CWV.”
One follow-up question (harder): How do you prove causality for a regression?

A teammate added 'use client' to the root layout. What’s your response?

Short answer: Push back-this inflates client JS and breaks server-first benefits.

Deep answer:

  • Root boundary makes too much UI client-side
  • Prefer server layout + client leaves
  • Use a small client wrapper only when truly needed

Common misconception / wrong answer: “It’s just one file.”
One follow-up question (harder): How do you enforce this via lint rules and code review?

Coding Tasks for Next JS Interview Questions with Solutions/Pseudocode

Build GET /api/products?limit=10 with a Route Handler.

Short answer: Parse searchParams, validate, and return JSON with Response.json.

Deep answer:

  • Use new URL(request.url)
  • Clamp and validate limit
  • Return correct status for invalid input

Common misconception / wrong answer: “Use Express req.query.”
One follow-up question (harder): Add OPTIONS for CORS preflight.

// app/api/products/route.ts
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const limitRaw = Number(searchParams.get('limit') ?? 10)
  const limit = Number.isFinite(limitRaw) ? Math.min(Math.max(limitRaw, 1), 50) : 10
  const products = await getProducts({ limit }) // pseudo
  return Response.json({ products })
}

Implement a Server Action that creates an item and revalidates /items.

Short answer: Validate input, write to DB, then call revalidatePath('/items').

Deep answer:

  • Validate at entry
  • Write to DB
  • Revalidate the page that displays the data

Common misconception / wrong answer: “Client state update is enough.”
One follow-up question (harder): How do you prevent duplicate submits (idempotency key)?

'use server'
import { revalidatePath } from 'next/cache'

export async function createItem(formData: FormData) {
  const name = String(formData.get('name') ?? '').trim()
  if (!name) return { ok: false, error: 'Name required' }

  await db.item.create({ name }) // pseudo
  revalidatePath('/items')
  return { ok: true }
}

Add tag-based caching and invalidate after an update.

Short answer: Add tags to cached fetches, then revalidateTag('products') after writes.

Deep answer:

  • Tags scale across many routes
  • Invalidate minimal set after mutation
  • Keep tags consistent naming

Common misconception / wrong answer:revalidateTag works without tagging.”
One follow-up question (harder): How would you tag by product:{id} and category:{slug}?

await fetch('https://api.example.com/products', {
  cache: 'force-cache',
  next: { tags: ['products'] },
})
// after update:
revalidateTag('products')

Implement a deep-linkable modal (Parallel + Intercepting) (pseudocode).

Short answer: Use @modal slot + (.) interception for modal view while keeping full-page route.

Deep answer:

  • Layout renders {children}{modal}
  • Slot has default.tsx returning null
  • Intercept detail route into slot

Common misconception / wrong answer: “Just store state in URL params.”
One follow-up question (harder): When do you need (..) interception instead of (.)? (File-system conventions: Intercepting Routes)

Write a realistic loading.tsx (skeleton).

Short answer: Skeletons matching real layout reduce perceived latency and layout shift.

Deep answer:

  • Mirror the UI structure
  • Avoid spinners-only
  • Keep it lightweight

Common misconception / wrong answer: “Spinner is enough UX.”
One follow-up question (harder): When do you prefer Suspense fallback vs segment loading?

// app/items/loading.tsx
export default function Loading() {
  return (
    <div>
      <div className="h-8 w-48 bg-gray-200 rounded" />
      <div className="mt-4 space-y-2">
        <div className="h-20 bg-gray-200 rounded" />
        <div className="h-20 bg-gray-200 rounded" />
        <div className="h-20 bg-gray-200 rounded" />
      </div>
    </div>
  )
}

Write middleware that redirects /app/* unauth users to /login.

Short answer: Check a cookie/token; redirect via NextResponse.

Deep answer:

  • Use matcher to scope
  • Preserve next param
  • Avoid DB in middleware

Common misconception / wrong answer: “Do full permission queries in middleware.”
One follow-up question (harder): How do you prevent open redirects?

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(req: NextRequest) {
  const isAuthed = Boolean(req.cookies.get('session')?.value)
  if (!isAuthed && req.nextUrl.pathname.startsWith('/app')) {
    const url = req.nextUrl.clone()
    url.pathname = '/login'
    url.searchParams.set('next', req.nextUrl.pathname)
    return NextResponse.redirect(url)
  }
  return NextResponse.next()
}

export const config = { matcher: ['/app/:path*'] }

Fix hydration mismatch caused by time rendering.

Short answer: Render time only on one side (prefer client effect for “now”).

Deep answer:

  • Avoid time in server render
  • Use useEffect to set client time
  • Keep initial markup stable

Common misconception / wrong answer: “Warnings don’t matter.”
One follow-up question (harder): How do you handle locale formatting safely?

'use client'
import { useEffect, useState } from 'react'

export function ClientTime() {
  const [t, setT] = useState('-')
  useEffect(() => setT(new Date().toLocaleTimeString()), [])
  return <span>{t}</span>
}

Create a safe fetch wrapper (pseudocode).

Short answer: Normalize non-2xx responses into typed errors and keep logs safe.

Deep answer:

  • Throw typed errors on non-OK
  • Include request IDs for debugging
  • Don’t leak secrets in errors

Common misconception / wrong answer: “Return null on failures.”
One follow-up question (harder): How do you retry GETs safely without retrying POSTs?

Server-rendered pagination with searchParams (no client fetch).

Short answer: Read searchParams.page, fetch server-side, render links.

Deep answer:

  • searchParams drives server render
  • Use Link for navigation
  • Cache strategy depends on data freshness

Common misconception / wrong answer: “Need client state.”
One follow-up question (harder): How do you ensure stable URLs for SEO?

export default async function Page({
  searchParams,
}: { searchParams: { page?: string } }) {
  const page = Math.max(Number(searchParams.page ?? 1), 1)
  const data = await getPage({ page }) // pseudo
  return <List data={data} />
}

Optimistic UI with a Server Action (pseudocode).

Short answer: Update UI immediately, then reconcile with server result + revalidation.

Deep answer:

  • Optimistic add/remove improves perceived speed
  • Roll back on failure
  • Revalidate to sync source of truth

Common misconception / wrong answer: “Optimistic UI replaces server invalidation.”
One follow-up question (harder): How do you prevent double submits reliably?

Pages Router Legacy Still Asked

What is getStaticProps?

Short answer: Pages Router API to fetch data at build time (SSG).

Deep answer:

  • Runs at build, not in browser
  • Can use revalidate (ISR)
  • Not used in App Router

Common misconception / wrong answer: “Runs every request.”
One follow-up question (harder): What’s the App Router replacement pattern?

What is getServerSideProps?

Short answer: Pages Router API to fetch data on every request (SSR).

Deep answer:

  • Runs server-side per request
  • Useful for auth/dynamic content
  • Migrates to Server Components patterns

Common misconception / wrong answer: “Faster than SSG.”
One follow-up question (harder): How do you cache SSR safely without leaking user data?

What is getStaticPaths?

Short answer: Pre-defines which dynamic routes get pre-rendered in Pages Router.

Deep answer:

  • Controls SSG for dynamic routes
  • App Router uses generateStaticParams
  • Needs strategy for large datasets

Common misconception / wrong answer: “It fetches page data.”
One follow-up question (harder): How do you handle millions of paths?

What are API Routes in Pages Router?

Short answer: Endpoints under pages/api/* using Node-style handlers.

Deep answer:

  • Legacy but still common in older codebases
  • App Router prefers Route Handlers
  • Migration can be incremental

Common misconception / wrong answer: “API Routes are gone.”
One follow-up question (harder): How do you migrate to Route Handlers safely?

What is _app.tsx?

Short answer: Pages Router wrapper for global providers and shared layout.

Deep answer:

  • Global providers (theme, state)
  • Replaced by app/layout.tsx in App Router
  • Still exists in hybrid/migration apps

Common misconception / wrong answer: “App Router still uses _app.”
One follow-up question (harder): How do you move providers without breaking hydration?

What is _document.tsx?

Short answer: Pages Router customization of the HTML document.

Deep answer:

  • Controls <html> and <body> setup
  • App Router uses root layout + metadata APIs
  • Not for per-page data fetching

Common misconception / wrong answer: “Put SEO tags here.”
One follow-up question (harder): What is the App Router approach to metadata?

What is shallow routing?

Short answer: Updating the URL without rerunning certain data methods in Pages Router.

Deep answer:

  • Useful for filter UIs in legacy pages
  • App Router uses searchParams patterns instead
  • Often replaced by server rendering based on search params

Common misconception / wrong answer: “Shallow routing is default.”
One follow-up question (harder): How do you build filter UIs in App Router without client fetching?

How do you migrate Pages Router to App Router?

Short answer: Incrementally: add app/, migrate route-by-route, replace legacy data fetching.

Deep answer:

  • Start new routes in app/
  • Move layouts/providers carefully
  • Migrate APIs to Route Handlers where it makes sense (Route Handlers)

Common misconception / wrong answer: “Rewrite everything at once.”
One follow-up question (harder): What’s your migration strategy for auth + caching?

Last-minute Revision (10 bullets)

Download PDF

Want a Next JS interview questions PDF for offline prep?

FAQs

What should freshers focus on first?

Answer:

Routing basics, Server vs Client components, loading/error patterns, and hydration fundamentals.

  • page/layout/loading/error/not-found conventions
  • 'use client' boundaries
  • Deterministic rendering to avoid hydration bugs

What do 3–5 year candidates get grilled on?

Answer:

Caching, revalidation, middleware tradeoffs, routing patterns (modals), and form/mutation flows.

  • Caching layers and invalidation
  • Route Handlers vs Server Actions
  • Parallel + intercepting routes

Do companies still ask Pages Router questions?

Answer:

Yes especially migrations and getServerSideProps/getStaticProps in older codebases.

  • Many apps are still migrating
  • Interviewers test your migration reasoning
  • App Router knowledge still dominates for new builds

Server Actions vs Route Handlers – which should I use?

Answer:

Actions for first-party UI forms; handlers for explicit HTTP APIs and integrations

  • Actions: tight UI integration, less boilerplate
  • Handlers: multi-client contracts, webhooks
  • Security applies to both (auth, validation)

Why is my data stale after updating the database?

Answer: You’re hitting a cache and not invalidating the correct cache layer.

  • Confirm fetch caching options
  • Ensure you invalidate tags/paths after mutation
  • Watch dev HMR cache behavior

How do I prevent hydration errors?

Answer:

Keep server HTML and client initial render identical.

  • Remove non-determinism
  • Move browser-only logic to effects
  • Keep client boundaries small

 

Is Next.js good for building APIs?

Answer:

Yes for BFF endpoints and webhooks via Route Handlers; large public APIs may fit better in a dedicated service.

  • Co-locate UI + lightweight APIs
  • Keep heavy jobs in workers
  • Separate public APIs when contracts and scaling demand it

How should I prepare for a senior Next.js interview?

Answer:

Practice tradeoffs: caching, auth/security, streaming, architecture, and real debugging stories.

  • Explain “why”, not just “how”
  • Use concrete examples and metrics
  • Show guardrails against caching/security bugs

What’s the most common mistake candidates make?

Answer:

They can’t clearly explain App Router boundaries and caching/invalidation.

  • Confuse SSR with Server Components
  • Don’t understand caching layers
  • Forget invalidation after mutations

Conclusion

If you can explain why Next.js behaves the way it does (not just what it does), you’ll stand out in interviews. In 2026-style Next.js rounds, the real signal is App Router fluency: when to keep components server-first, how to draw clean client boundaries, how to design caching + revalidation that won’t ship stale data, and how to use modern routing patterns (route groups, parallel routes, intercepting routes) to build UX like deep-linkable modals correctly.

Use this guide like a checklist: practice answering the short version in 30 seconds, then the deep bullets in 2–3 minutes, and finish by tackling the scenario questions and coding tasks until you can solve them without looking.

Finally, revise the gotchas because most candidates fail on edge cases (hydration mismatches, caching surprises, and auth + runtime tradeoffs), not on definitions. Bookmark this page, generate your PDF copy using Print → Save as PDF, and keep drilling until your answers sound like someone who has shipped real Next.js apps.

Leave a Comment

error: Content is protected !!