THN Interview Prep

Next.js — App Router, SSR & caches

The App Router ties routing, React Server Components, data fetching, caching, streaming, metadata, and deployment runtime together. The senior skill is separating those concerns mentally even when the framework composes them in one file tree.

Core details

App Router primitives: app/ segments, layout, page, loading, error, not-found, route groups, parallel routes, and intercepting routes. Nested layouts persist across navigation, so state and error/loading boundaries must be placed intentionally.

Server Components by default: a component is server-rendered unless a "use client" boundary is introduced. Server components can fetch data and keep server-only code out of the client bundle. Client components hydrate, handle events, use state/effects, and can receive only serializable props.

Cache layers to separate:

LayerStoresMain risk
Request Memoizationrepeated function/fetch results during one server renderassuming it persists across users
Data Cachefetched/cached data across requestsstale business data
Full Route Cacherendered HTML/RSC outputstale personalization
Router Cacheclient-side RSC payload by segmentsoft navigation showing old server state
CDN/browser cacheHTTP responses/assetswrong keying or unsafe public caching

Rendering modes: static/prerendered output, request-time SSR, streaming with Suspense, and static shells with dynamic holes through newer cache/prerendering features. The fallback UI matters as much as the mechanism because poor skeletons create layout shift and user confusion.

Mutations: Server Actions and route handlers are server entrypoints. Authenticate, authorize, validate input, make writes idempotent where needed, and invalidate the right cache boundary after success.

Runtime choice: Edge runtime can reduce latency for lightweight request shaping, redirects, and auth checks, but Node runtime is often required for database drivers, file APIs, long-lived connections, and heavier libraries.

Understanding

Next’s App Router merges routing, data fetching, and the component graph tightly. Staff-level clarity separates CDN/full-route output, fetch/data cache policies, and client Router Cache behavior. Bugs often arrive as stale personalization: middleware saw auth, but a server component still rendered guest UI because the route or data was cached under the wrong assumptions.

Server Components are not an RPC mechanism from the browser. They are a server-rendered component graph serialized into an RSC payload. Client components receive serializable props from that graph, hydrate, and handle browser interactions.

Streaming is most valuable when the shell is useful and stable. If every important region suspends behind a spinner, streaming only moves the blank state around. Reserve dimensions, keep navigation usable, and align loading states with the user’s task.

Practical examples

RequirementLikely choiceRisk
Public marketing pageStatic/prerendered with long-lived assetsPreview and CMS invalidation workflow
Auth dashboardDynamic render or carefully keyed cacheStale or cross-user personalization
Product page with reviewsStatic shell + dynamic reviews if acceptableInconsistent freshness messaging
Checkout mutationServer Action or route handler with idempotencyDuplicate submit and stale router cache
Geolocation/auth middlewareEdge runtime if APIs fitNode-only packages and cold-start assumptions

Cache debugging order:

  1. Is the route static or dynamic?
  2. Is data cached, memoized per request, or uncached?
  3. Is the client Router Cache showing an old RSC payload?
  4. Is a CDN/browser cache serving old HTML or assets?
  5. Did a mutation call the right invalidation path?

Boundary placement rule: keep data-heavy display components on the server when possible; move only interactive controls, browser APIs, and stateful widgets behind "use client".

Senior understanding

LensSpeak to
SecurityNever pass secrets into client props; avoid caching auth HTML publicly; validate Server Action inputs
PerformanceRSC reduces shipped JS, but server waterfalls still hurt TTFB
OpsSelf-host vs managed platform, ISR/storage, runtime limitations, SSR error instrumentation
CorrectnessCache invalidation after mutations, deploy ordering for payload changes, deterministic hydration

Trap answers: “RSC solves all data loading” without discussing serialization and TTFB; ignoring cold start and connection-pool realities; treating client cache as magically consistent with server caches.

Failure modes

  • Adding "use client" to a layout and accidentally hydrating the whole route subtree.
  • Caching a route that reads auth-like state without marking it dynamic or keying safely.
  • Assuming router.refresh() invalidates every server/CDN/data cache.
  • Creating sequential server fetch waterfalls that dominate TTFB.
  • Passing class instances, functions, secrets, or non-serializable values across an RSC/client boundary.

Interview drill

Question: "A Next.js App Router page shows old data after a Server Action succeeds. Where do you look?"

Model answer structure:

  1. Name the cache layers separately: request memoization, Data Cache, Full Route Cache, Router Cache, CDN, and browser cache.
  2. Check the mutation result, whether the right tag/path was revalidated, and whether the client is showing an old Router Cache payload.
  3. Confirm the route's dynamic/static status and whether auth or cookies affect cache eligibility.
  4. Fix the narrow stale boundary: revalidate tag/path, refresh the client route, mark dynamic, or correct HTTP/CDN policy.
  5. Add a regression case that mutates, navigates away/back, and verifies fresh server state.

Follow-ups to expect:

  • "What happens when "use client" is placed too high?"
  • "Why do Server Components not automatically make TTFB fast?"
  • "When would Edge runtime be the wrong choice?"

Diagram

Loading diagram…

See also

Mark this page when you finish learning it.

Spotted something unclear or wrong on this page?

On this page