Frontend
May 28, 2026
1K Views
22 min read

Top 20 Next.js 15 Interview Questions: App Router, Server Actions & PPR (2026 Guide)

Still answering Next.js questions like it's 2023? Interviewers now filter on PPR, Server Actions security, Turbopack, and the new caching defaults. Master all 20 questions they actually ask in 2026 senior loops.

Advertisement
Top 20 Next.js 15 Interview Questions: App Router, Server Actions & PPR (2026 Guide)

Why Next.js 15 Is the Top Frontend Interview Filter in 2026

If you are applying for a senior frontend or fullstack role in 2026, there is an overwhelming probability that the interviewer will probe your Next.js 15 knowledge — specifically its architectural rewrites. Companies building on Vercel's ecosystem, from fintech unicorns to FAANG product teams, have made Next.js their default rendering stack. The framework's rapid evolution means surface-level React knowledge is no longer sufficient. Interviewers want to know that you deeply understand why defaults changed, when to opt into or out of caching, and how to secure Server Actions from unauthorized mutation.

This guide compiles the 20 most commonly asked Next.js 15 interview questions with precise, code-first answers. Each answer is structured to demonstrate engineering depth, not just pattern recitation. Whether you're targeting a US tech company, a European scale-up, or a remote-first startup, this guide prepares you for the real questions that filter senior candidates from junior ones.

⚡ Practice Next.js 15 Under Real Interview Pressure

Our AI interviews you like a senior engineer from Vercel, Stripe, or Google. Get a detailed rubric on your App Router and Server Components knowledge. Start free — no credit card needed.

Start Free AI Mock Interview →

Section 1: Caching Architecture Changes (Questions 1–5)

Frontend Architecture Exam Simulator

Ace Your Next React 19 & Frontend Interview

Test your skills on React 19 Server Actions, performance vital optimizations, and hydration loops in our proctored exam simulator.

Requires Camera & Fullscreen Setup

1. How does Next.js 15's default caching behavior differ from Next.js 14, and why did Vercel make this change?

This is the most commonly asked Next.js 15 question in 2026 senior loops. In Next.js 14, fetch() calls, Route Handlers, and Client Router Cache were all cached by default, which caused widespread confusion — developers reported pages rendering stale data without understanding why. In Next.js 15, Vercel made a decisive architectural reversal:

  • fetch() requests now default to cache: 'no-store' (dynamic, not cached).
  • GET Route Handlers are no longer automatically cached. You must explicitly add export const dynamic = 'force-static' to opt into caching.
  • Client Router Cache no longer stores Page components by default. Navigation now fetches fresh data from the server, unless explicitly configured with staleTimes.

The reason: applications that need real-time data (e-commerce inventory, dashboards, social feeds) were inadvertently shipping stale content. Opting into caching is now an explicit decision, reducing accidental staleness bugs in production.

2. What is the staleTimes configuration in Next.js 15 and when would you use it?

The new staleTimes configuration in next.config.js lets you control how long the Client Router Cache holds Page data (in seconds) before treating it as stale and fetching fresh data from the server:

// next.config.js
module.exports = {
  experimental: {
    staleTimes: {
      dynamic: 30,   // Pages fetched dynamically: cached for 30s
      static: 180,   // Statically generated pages: cached for 3 mins
    },
  },
};

Use this when you have pages that are expensive to re-fetch but tolerate short delays — for example, a user's notifications page where 30-second staleness is acceptable, but zero caching would create unnecessary server load.

3. Explain the unstable_cache API and when it replaces getStaticProps.

unstable_cache is Next.js 15's server-side data caching primitive that works inside Server Components and Server Actions. It wraps an async function with a configurable TTL and tag-based revalidation strategy:

import { unstable_cache } from 'next/cache';

const getCachedProducts = unstable_cache(
  async (categoryId) => {
    return await db.products.findMany({ where: { categoryId } });
  },
  ['products-by-category'],
  { revalidate: 3600, tags: ['products'] } // 1 hour TTL, tag-based invalidation
);

// Trigger revalidation anywhere in the codebase
import { revalidateTag } from 'next/cache';
revalidateTag('products'); // Instantly clears all caches tagged 'products'

This replaces getStaticProps revalidation patterns in the App Router world, providing far more granular control. Unlike ISR which revalidates entire pages, unstable_cache revalidates specific data dependencies.

4. What are the new React 19 async component patterns enabled in Next.js 15?

Next.js 15 is the first framework to ship with official React 19 support. The key interview-level change is that async functions can now be used directly as Server Components — but the critical addition is first-class support for useActionState, useFormStatus, and useOptimistic in form handling without any custom loader state scaffolding. This replaces the verbose loading/error state patterns from React 18.

5. What is the after() API in Next.js 15 and what problem does it solve?

The after() function is a major new addition in Next.js 15 that allows code to run after the response has been sent to the user. This solves a major production problem: secondary tasks like logging, analytics events, or cache warm-ups were previously blocking user response time:

import { after } from 'next/server';

export default async function CheckoutPage() {
  // This runs immediately and sends the response
  const order = await processOrder();

  // This runs AFTER the response is sent to the browser
  after(async () => {
    await logAnalyticsEvent('checkout_completed', { orderId: order.id });
    await warmInventoryCache(); // doesn't delay the user
  });

  return <OrderConfirmation order={order} />;
}

Section 2: Partial Prerendering & Rendering Strategy (Questions 6–10)

6. What is Partial Prerendering (PPR) and how does it unify static and dynamic rendering?

Partial Prerendering (PPR) is the most architecturally significant feature in Next.js 15. Before PPR, developers had to decide at the route level whether a page is static (SSG) or dynamic (SSR). This is a binary, all-or-nothing choice. PPR breaks this constraint by enabling both rendering modes within a single page, using React's <Suspense> boundaries as the signal:

  • Everything outside a <Suspense> boundary is prerendered to a static HTML shell during build time and delivered instantly from the CDN.
  • Everything inside a <Suspense> boundary is streamed dynamically from the server at request time, filled in after the static shell arrives.

The result: users see a fully rendered layout (header, navigation, article content) in milliseconds, while the personalized "recommended articles" sidebar or user cart streams in shortly after. This achieves both optimal LCP (from static shell) and full personalization (from dynamic streaming), eliminating the classic static-vs-dynamic trade-off.

7. How do you opt into PPR in a Next.js 15 project?

// next.config.js — Enable PPR incrementally
module.exports = {
  experimental: {
    ppr: 'incremental', // Opt pages in individually
  },
};

// app/dashboard/page.tsx — Enable PPR for this specific route
export const experimental_ppr = true;

export default function DashboardPage() {
  return (
    <main>
      <StaticHeader /> {/* Prerendered at build time */}
      <Suspense fallback={<UserSkeleton />}>
        <DynamicUserProfile /> {/* Streamed at request time */}
      </Suspense>
    </main>
  );
}

The incremental setting is crucial for production adoption — it lets teams migrate page-by-page without requiring a full application rewrite.

8. What is the difference between Streaming SSR and PPR?

This is a common interview trap. Streaming SSR (introduced in Next.js 13) and PPR are different mechanisms:

  • Streaming SSR: The entire page is rendered server-side, but the HTML is streamed chunk-by-chunk as each <Suspense> boundary resolves. The initial response is still dynamic and cannot be cached by a CDN.
  • Partial Prerendering (PPR): The static shell is genuinely prebuilt and served from CDN cache. Only the dynamic holes (inside Suspense boundaries) incur server compute. The TTFB for the static shell is effectively zero because it comes from the edge cache.
PPR gives you CDN-level performance for the static shell plus streaming for the dynamic parts — combining the best of both worlds.

9. How does Turbopack improve development experience in Next.js 15?

Turbopack became the default bundler for next dev in Next.js 15 (no longer behind an experimental flag). The performance improvements are dramatic:

  • Initial compile speed: Up to 76.7% faster than Webpack for large applications.
  • Hot Module Replacement (HMR): Up to 96.3% faster — changes reflect in under 100ms for most modules.
  • Incremental compilation: Only re-compiles changed modules and their dependents, not the entire module graph.
Critically, Turbopack only applies to next dev currently. Production builds (next build) still use Webpack/SWC. Interviewers may ask about this distinction.

10. How do you handle React compiler integration in Next.js 15?

Next.js 15 ships with an opt-in React Compiler integration. When enabled, the compiler automatically memoizes components and hooks, eliminating the need for manual useMemo, useCallback, and React.memo calls:

// next.config.js
module.exports = {
  experimental: {
    reactCompiler: true, // Enables automatic memoization
  },
};

However, the React Compiler requires strict adherence to React's rules of purity. Any component that mutates external state or produces side effects in render will be silently skipped by the compiler and will not receive automatic memoization benefits.

Section 3: Server Actions, Security & Data Mutations (Questions 11–15)

11. What specific security threats do Server Actions introduce, and how does Next.js 15 mitigate them?

Server Actions are publicly accessible HTTP endpoints, which creates a critical attack vector. If an action ID is guessable or if the action doesn't verify caller identity, any external actor can invoke mutations (write to your database, delete records, send emails). Next.js 15 implements three automatic protections:

  1. Randomized Action IDs: Each Server Action is assigned a cryptographically secure, non-guessable identifier at build time. These IDs rotate with each deployment.
  2. Dead Code Elimination: Unused server actions are never compiled into the client bundle, reducing the exposed surface area.
  3. Origin Header Checking: Next.js 15 automatically validates that mutations via Server Actions originate from the same domain (CSRF protection). Cross-origin POST requests are blocked by default.

12. How do you implement authorization inside Server Actions?

'use server';
import { auth } from '@/lib/auth';
import { db } from '@/lib/db';

export async function deletePost(postId: string) {
  // Step 1: Always authenticate inside the action
  const session = await auth();
  if (!session?.user) {
    throw new Error('Unauthorized: You must be logged in.');
  }

  // Step 2: Authorize — check ownership
  const post = await db.posts.findUnique({ where: { id: postId } });
  if (post?.authorId !== session.user.id) {
    throw new Error('Forbidden: You do not own this post.');
  }

  // Step 3: Perform the mutation
  await db.posts.delete({ where: { id: postId } });
  revalidatePath('/posts');
}

A critical interview mistake: never trust client-passed user IDs. Always re-derive the authenticated user's identity from the server-side session inside the action.

13. What is the experimental_taintUniqueValue API and when is it critical?

React's taint APIs prevent sensitive values from accidentally leaking to the client. While experimental_taintObjectReference taints entire objects, experimental_taintUniqueValue taints specific scalar values like API keys, private tokens, or database URIs:

import { experimental_taintUniqueValue } from 'react';

const apiKey = process.env.STRIPE_SECRET_KEY;
experimental_taintUniqueValue(
  'Never pass the Stripe secret key to the client.',
  process,
  apiKey
);

// Now if any Server Component tries to pass apiKey as a prop to a
// Client Component, React will throw a build-time error — not a runtime one.

14. How do you implement optimistic UI updates with Next.js 15 Server Actions?

'use client';
import { useOptimistic } from 'react';
import { toggleLike } from './actions';

function LikeButton({ postId, initialLikes }) {
  const [optimisticLikes, addOptimisticLike] = useOptimistic(
    initialLikes,
    (currentLikes, increment) => currentLikes + increment
  );

  async function handleLike() {
    addOptimisticLike(1); // Instant UI update
    await toggleLike(postId); // Actual server mutation
  }

  return (
    <button onClick={handleLike}>
      ❤️ {optimisticLikes} Likes
    </button>
  );
}

If the server action fails, React automatically reverts the optimistic state to the pre-mutation value, ensuring the UI stays consistent with the actual database state.

15. What is the difference between revalidatePath and revalidateTag, and when should you use each?

  • revalidatePath('/products'): Invalidates all cached data for a specific URL path. Use when a mutation affects a specific page's content (e.g., after adding a new product, revalidate the products listing page).
  • revalidateTag('products'): Invalidates all cached data tagged with a specific label, regardless of which page uses it. Use when the same data is shown on multiple pages (e.g., a product featured on the homepage, product page, and category page all share the 'products' tag and can all be invalidated with one call).

Section 4: Practical & System Design Questions (Questions 16–20)

16. How would you implement middleware-based authentication in Next.js 15?

Next.js Middleware runs at the edge, before any page or API route processes the request. It's the ideal place for session verification:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { verifyJWT } from '@/lib/auth';

export async function middleware(request: NextRequest) {
  const token = request.cookies.get('session')?.value;

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  try {
    await verifyJWT(token);
    return NextResponse.next(); // Allow request to continue
  } catch {
    return NextResponse.redirect(new URL('/login', request.url));
  }
}

export const config = {
  matcher: ['/dashboard/:path*', '/account/:path*'],
};

17. What is the forbidden() and unauthorized() function in Next.js 15?

Next.js 15 introduced two new helper functions that throw standardized HTTP error responses directly from Server Components:

import { forbidden, unauthorized } from 'next/navigation';

export default async function AdminPage() {
  const session = await getSession();
  if (!session) unauthorized(); // Throws 401 - renders error.tsx
  if (session.role !== 'admin') forbidden(); // Throws 403 - renders error.tsx

  return <AdminDashboard />;
}

These replace the previous pattern of manually returning redirect responses or throwing generic errors, and they integrate cleanly with Next.js's built-in error boundary file conventions.

18. How would you architect a Next.js 15 e-commerce product page for maximum performance?

The optimal architecture leverages PPR to maximize Lighthouse scores while serving personalized data:

  • Static Shell (CDN-served): Product title, description, images, static category breadcrumbs.
  • Dynamic Stream 1: Real-time stock levels (changes frequently, wrapped in Suspense).
  • Dynamic Stream 2: Personalized "Recommended for You" sidebar based on user history.
  • Dynamic Stream 3: User's existing cart item count in the header.

This architecture delivers a Core Web Vitals score that's optimal because the LCP (hero product image) is in the static shell, while user-specific content streams in without blocking the paint.

19. How has Next.js 15 improved TypeScript support?

Next.js 15 introduces statically typed route parameters, eliminating a major class of runtime errors. Previously, params and searchParams in page components were typed as simple objects, meaning any key access was unchecked. In Next.js 15, these props are now fully typed based on the file system route structure, and params and searchParams are now Promises — they must be awaited:

// app/products/[id]/page.tsx
type Props = {
  params: Promise<{ id: string }>;
  searchParams: Promise<{ [key: string]: string | undefined }>;
};

export default async function ProductPage({ params, searchParams }: Props) {
  const { id } = await params;
  const { color } = await searchParams;
  // id is typed as string; accessing params.unknownKey is a TypeScript error
}

20. What questions should you ask the interviewer about their Next.js architecture?

Asking smart follow-up questions is what separates 10x candidates from average candidates. These demonstrate senior engineering thinking:

  • "Are you using PPR or is your architecture still route-level static/dynamic segregation? What's blocking adoption?"
  • "How are you handling Server Action authorization at scale — do you have a centralized auth middleware or per-action checks?"
  • "What's your current Turbopack adoption? Are you seeing meaningful HMR improvements in your monorepo?"
  • "How are you managing cache invalidation across your edge CDN and Next.js's data cache layer?"

Each question signals that you don't just know the framework — you understand the operational concerns of maintaining it at production scale.

Expand Your Frontend Interview Preparation

Ready to Ace Your Next.js 15 Interview?

Reading about Next.js is passive. Being grilled on caching and PPR under timed conditions is how you land offers. Start our dedicated Next.js mock loop now — free, no signup required.

Practice Next.js 15 Mock Interview (Free) →
AI Resume Truth Serum

Does Your Resume Pass FAANG Audits?

Before applying, upload your resume. Our lightweight parsing agents will instantly scan for contradictions, project-scaling metrics, or over-claimed achievements.

Drag & drop your PDF resume

or click to browse local files (PDF only, max 5MB)

Ace Your Frontend & React 19 Loop

Practice dynamic React 19 features, Server Actions, hydration optimizations, and rendering loops under real exam conditions.

✅ Dynamic Product Match🚀 Trusted by 1k+ Engineers
Advertisement
Share this article:
Found this helpful?
Next.js 15
Next.js
React
Frontend
Interview Questions
Server Actions
PPR
Turbopack
App Router
📋 Legal Disclaimer & Copyright Information

Educational Purpose: This article is published solely for educational and informational purposes to help candidates prepare for technical interviews. It does not constitute professional career advice, legal advice, or recruitment guidance.

Nominative Fair Use of Trademarks: Company names, product names, and brand identifiers (including but not limited to Google, Meta, Amazon, Goldman Sachs, Bloomberg, Pramp, OpenAI, Anthropic, and others) are referenced solely to describe the subject matter of interview preparation. Such use is permitted under the nominative fair use doctrine and does not imply sponsorship, endorsement, affiliation, or certification by any of these organisations. All trademarks and registered trademarks are the property of their respective owners.

No Proprietary Question Reproduction: All interview questions, processes, and experiences described herein are based on community-reported patterns, publicly available candidate feedback, and general industry knowledge. MockExperts does not reproduce, distribute, or claim ownership of any proprietary assessment content, internal hiring rubrics, or confidential evaluation criteria belonging to any company.

No Official Affiliation: MockExperts is an independent AI-powered interview preparation platform. We are not officially affiliated with, partnered with, or approved by Google, Meta, Amazon, Goldman Sachs, Bloomberg, Pramp, or any other company mentioned in our content.

Get Weekly Dives

Stay Ahead of the Competition

Join 1k+ engineers receiving our weekly deep-dives into FAANG interview patterns and system design guides.

No spam. Just hard-hitting technical insights once a week.