Representative interview topic

Frontend Interview: How Do You Choose Between CSR, SSR, SSG, and ISR?

FrontendHard
Offer.cc Editorial TeamPublished Updated

Question

A Next.js 16 commerce platform has 20,000 public guides updated weekly, one million product pages, real-time search results, and signed-in order pages. Product descriptions may be five minutes stale, but price and inventory must be confirmed live before checkout. Choose CSR, SSR, SSG, or ISR for each route and explain SEO, initial delivery, server load, cache invalidation, failure behavior, and verification.

Prompt and applicable scenarios

A Next.js 16 commerce platform has four page families:

  • /guides/[slug]: 20,000 public guides, edited weekly, whose body text should be reliably discoverable by search engines;
  • /products/[id]: one million public product pages whose descriptions and images may be up to five minutes stale, while price and inventory must be confirmed live before checkout;
  • /search?q=: results that vary with the query, filters, and current catalog state; the first view should be shareable, but every query combination need not be indexed;
  • /account/orders: private pages that vary by signed-in user and must enter neither a shared cache nor a search index.

The team wants less origin rendering without sacrificing discoverability on public pages or responsiveness on interactive ones. The candidate must choose a primary rendering strategy for each route family, then say which regions can mix in a different strategy. The answer must define a freshness bound, invalidation trigger, failure output, and production proof.

A 2026 public frontend interview guide explicitly lists choosing a rendering strategy for a given page and deciding between ISR and SSR. A separate frontend question bank has a dedicated CSR, SSR, SSG, and ISR comparison. Many search results stop at a four-row pros-and-cons table. Few combine invalidation, live verification of critical fields, an external CDN, and failure semantics. This question adds that production decision layer.

What the interviewer evaluates

First, does the candidate define page requirements before choosing an acronym? Rendering location is not the goal. Public indexability, initial content, freshness, personalization, traffic, page count, interaction cost, and failure behavior are the inputs. “SSR is good for SEO” cannot decide an order page or a million-page catalog.

Second, do they understand where each strategy places cost?

StrategyWhen HTML is producedMain advantageMain cost
CSRAfter JavaScript runs in the browserDirect updates for private, highly interactive stateInitial content depends on scripts and data requests; client cost is higher
SSROn the server for each requestFresh or personalized HTML per requestLatency and availability depend on rendering and upstreams; compute grows with traffic
SSGAt build timeStatic files cache easily and spare the originReleases couple to page count; updates usually require regeneration
ISRStatically first, then regenerated by time or eventStatic delivery with incremental updatesExplicit staleness, invalidation propagation, and regeneration-failure semantics

Third, can they identify a hybrid? A product page can use ISR for an indexable description, fetch current delivery choices on the client, and revalidate price and inventory in the checkout service. Choosing ISR does not make every field safe to serve stale. Choosing SSR does not eliminate client JavaScript or hydration.

Fourth, can they turn the choice into a testable contract? A strong answer states how stale content may become, who invalidates it, what a regeneration failure shows, whether cache keys include user or region, and how much JavaScript a real browser downloads. It supplies build, runtime, cache, and business-correctness metrics.

Questions to clarify before answering

  • Is the page public and intended for indexing? Public body text, title, canonical, and status should preferably

be present in the initial response. Private orders need authentication, no shared caching, and an explicit noindex policy.

  • How fast is “real time”? A description may be five minutes old, while price and inventory affect a payment

promise. Those fields cannot inherit the same cache SLA.

  • Which dimensions change the content? Locale, region, currency, authentication, and experiment group can alter a

cache key. A missing dimension can serve wrong or private data; too many dimensions destroy hit rate.

  • What are the page count and update distribution? Building one million URLs on every release is unattractive. If

95% are long-tail pages, prebuild popular paths and generate the rest on first access.

  • Are publication events reliable? Can the CMS or catalog emit an entity ID? If events can be lost, add time-based

expiry, reconciliation, or manual invalidation as compensation.

  • How is caching deployed? One process, multiple containers, a managed platform, and an external CDN propagate

invalidation differently. Purging the Next.js server cache may leave another CDN copy intact.

  • On failure, is old content safer than wrong content? Serving the last successful guide is usually reasonable.

Price, inventory, and order state must be confirmed by an authoritative service.

  • What are the success gates? Define indexable-content completeness, TTFB/LCP/INP, hit rate, regeneration delay,

content age, origin render QPS, build duration, error rate, and checkout conflict rate.

30-second answer framework

“I split routes by publicity, per-request variation, freshness, and page count. Guides are primarily SSG and are invalidated by path on publication. Product details use ISR for a low-cost, indexable body, with catalog events plus a five-minute time fallback; price and inventory refresh in the client and are confirmed again by checkout. Search is SSR per query, without sharing responses that contain user dimensions. Private orders use an authenticated server shell and CSR data updates. I verify cache behavior in a production build and monitor content age, hit rate, TTFB, LCP, JavaScript size, regeneration failure, and business conflicts, without trusting one Lighthouse score.”

Step-by-step deep dive

Step 1: Use one decision matrix to select the primary strategy per route

Put every page family through the same matrix instead of starting from framework APIs:

RoutePrimary strategyReasonMixed region
GuidesSSG + event regenerationPublic, infrequent edits, identical body for all usersInvalidate path after publish; reconcile periodically
Product detailISRMany public URLs; body tolerates short stalenessLive price/inventory, server recheck at checkout
Search resultsSSRHuge query space; results vary per requestBrowser owns filters and subsequent interaction
Private ordersPrimarily CSRPer-user, non-indexed, interaction-heavyServer may emit an authenticated shell and skeleton

“SSG plus publication invalidation” uses incremental regeneration at runtime, although its primary content model remains a prerendered static page. It is cheaper than SSR for every request to 20,000 guides and more targeted than rebuilding the whole site for a typo. All guides can be built initially; if the set grows, prebuild popular paths and generate the rest on first request.

ISR fits product details because the body is public, repeatedly viewed, and allowed to be briefly stale. A five-minute revalidation setting is not a hard five-minute maximum in every condition. The first request after the interval may still receive stale HTML while background regeneration starts. A low-traffic page may trigger later, and a failed regeneration extends the old version's lifetime. If publication should appear promptly, invalidate by product ID after the write succeeds and keep the time window only as compensation.

The search query space is too large to prebuild. SSR can put query-consistent content and a real status in the first response. Cache keys must include every public parameter that changes results. Responses involving authentication or personalized price should be private or uncached. The client takes over filters, pagination, and input after the first view.

The order page gains nothing from public indexable HTML. The server may establish an authenticated shell, while CSR loads the list and live state from a user API. That response must not enter a shared cache. CSR is a rendering choice; authentication and authorization still belong on the server.

Step 2: Express ISR as a freshness and invalidation contract

The product route needs two contracts:

text
Cacheable body: name, description, images, category
  Event invalidation: after product:{id} updates successfully
  Time fallback: 300 seconds
  Failure semantics: serve the last successful version and alert

Critical live fields: price, inventory, delivery eligibility
  Page display: refresh from the authority and show update time
  Checkout submission: recompute on the server and confirm changes

The Next.js ISR guide states that the first request after the interval can receive stale content while regeneration runs in the background. Subsequent requests receive the new version after success. If regeneration throws, the last successful version stays cached and another request retries. Monitor content age; a configuration value is not proof that the business SLA is met.

In Next.js 16, revalidateTag(tag, "max") uses stale-while-revalidate and fits articles, catalogs, or product bodies that allow a brief delay. When a user must immediately read their own write, updateTag in a Server Action provides read-your-writes semantics. They are not interchangeable “clear cache” buttons. The event source, allowed staleness, and call site determine which operation fits.

Draw the propagation chain too. Browser, CDN, Next.js route cache, data cache, and upstream service can each have a TTL. The official CDN guide warns that path or tag invalidation in Next.js does not automatically purge a separately cached CDN copy. If an external CDN is added, purge matching HTML and data variants too, or make its TTL satisfy the same freshness contract. Multi-instance self-hosting also needs a shared cache or synchronized tag state so one instance does not remain stale.

Step 3: Handle SEO, interaction, and failure boundaries separately

Google can execute JavaScript and index rendered HTML, but rendering enters a queue, and other bots may not execute JavaScript. Public guides and product bodies should put visible text, title, canonical, structured data, and the right status in initial HTML. Do not return an empty 200 shell and let the client turn a missing product into “not found.” The server or static-generation path should produce the real 404.

Prerendering does not automatically make a page fast or interactive. An SSR/SSG/ISR page with too many client components still pays JavaScript download, parse, and hydration cost. Well-split CSR with nearby data can perform well on signed-in navigation. Measure TTFB, LCP, INP, long tasks, downloaded and executed JavaScript, and time from visible to interactive.

Classify failure behavior by data risk:

  • Guide or product-body regeneration fails: serve the last successful version, expose its update time, and alert on age.
  • Search upstream times out: show a retryable failure or an explicitly allowed short cache, not a fabricated empty result.
  • Price or inventory API fails: do not confirm an old value; require a retry before checkout.
  • Order API fails: retain already loaded UI and offer retry; never fall back across users through a shared cache.
  • Invalidation events lag: reconcile entity versions, find pages behind the authority, and issue compensating invalidation.

Step 4: Verify with a production build and business metrics

Development mode cannot prove static-generation and ISR behavior. Build for production and run the production server before verifying all four route families. Cover at least these tests:

  1. Inspect build output and confirm each route is static, on-demand, or dynamic as intended, rather than accidentally

becoming SSR because of one uncached read.

  1. Request one product repeatedly to prove hits; then update it and record event, invalidation, and first-new-HTML times.
  2. Fail the regeneration dependency, prove the last successful body remains and the error is recorded, then recover.
  3. Request different locales, regions, currencies, and auth states to prove complete keys and private-response isolation.
  4. Fetch initial HTML directly to verify body, metadata, canonical, and 404, then use a real browser for hydration.
  5. Model an external CDN and multiple instances; prove invalidation reaches every layer and instance.
  6. With the real page distribution, measure build time, origin render QPS, hit rate, TTFB, LCP, INP, and JS cost.
  7. Compare displayed values with checkout authority and watch price/inventory conflicts, so optimization cannot change

transaction correctness.

Migrate route by route. Observe current SSR traffic and correctness, then move low-risk guides to static delivery. Run product ISR in shadow mode first by recording what the cache would return. Serve it only after invalidation proves reliable. Keep a per-route rollback to the prior strategy, triggered by correctness or content-age limits.

High-quality sample answer

“I would not choose one acronym for the application. Guides are public, uniform, and infrequently edited, so I build static HTML and invalidate the path after a successful CMS publication. Initial text stays indexable and almost every request uses static caching. There are one million product URLs, so I prebuild hot products and generate the rest on first access. The product body uses ISR, invalidated by product ID, with 300 seconds only as lost-event compensation. The first request after expiry may still receive old content and start background generation, so I monitor the gap between entity update time and cache generation time instead of promising that 300 means a hard maximum.”

“Price, inventory, and delivery eligibility do not inherit the body's stale window. The browser refreshes them from the authority, and checkout recomputes them on the server and asks for confirmation if price changed. Search has too many combinations and changes per query, so its first view is SSR and the client owns later filters. Responses that contain authentication or personalized conditions never enter a shared cache. Orders use an authenticated shell and CSR data, with server-side user authorization and noindex.”

“I verify the real route modes with a production build, then test hits, event invalidation, the 300-second fallback, regeneration failure, and recovery. An external CDN must purge with Next.js, and multiple instances need synchronized invalidation. I inspect initial public HTML for body, canonical, and status, then measure TTFB, LCP, INP, and JavaScript cost in a real browser. Finally, I compare displayed and checkout prices. Passing performance while transaction correctness declines is still failure.”

Common mistakes and improvements

  • Choose one strategy for the application → Public, search, and private pages have different requirements →

Decide per route and sometimes per data region.

  • Treat SSR as an SEO guarantee → Metadata, status, canonical, and crawlable links can still be wrong →

Inspect initial HTML and crawler output.

  • Say CSR is completely invisible to search → Google can render JavaScript, with queueing and differing bot

capabilities → Prerender key public content and describe the limitation accurately.

  • Treat revalidate=300 as a hard five-minute SLA → Low traffic, background work, and failure extend staleness →

Combine event invalidation, age monitoring, and a time fallback.

  • Give the entire page one freshness rule → Description tolerates staleness; price and inventory cannot be promised

from it → Split data by risk and recheck at the transaction boundary.

  • Purge only Next.js → An external CDN or another instance may retain a copy → Map every cache and test propagation.
  • Assume prerendered means fast → Excess JavaScript, hydration, and slow upstreams still hurt → **Measure network,

main thread, Web Vitals, and server metrics.**

  • Test ISR only in development → Development behavior does not represent production caching → **Use a production

build and server for hit, invalidation, and failure tests.**

  • Use stale pages to hide every error → Empty search, stale price, or cross-user orders cause wrong decisions or

leaks → Define stale-if-error by data risk.

Follow-up questions

Can ISR remain if product changes must be globally visible within ten seconds?

Yes, but ten seconds must become an end-to-end invalidation SLO. After the catalog transaction commits, reliably emit a versioned event, synchronize tag invalidation across all Next.js instances, purge the external CDN, and probe the new version from multiple regions. Time revalidation is compensation, not a ten-second guarantee. If the purge chain cannot meet the target, read that field dynamically or use a shorter cache path whose bound can be demonstrated.

Why can statically generating one million products be a problem?

It couples build time, artifacts, and release risk to the page count, although many long-tail pages may never be read. Prebuild high-traffic products and generate the rest on first request. Bound regeneration concurrency, prevent a hot event from causing a regeneration storm, and preserve reliable 404 behavior for missing products.

Can an SSR response be cached in a CDN?

Shareability depends on whether the response is identical across every cache-key dimension, not on the name SSR. A public search response with a complete key and permitted short staleness can be cached cautiously. A response involving cookies, user permissions, personalized pricing, or experiment membership should be private or uncached. Test Vary, key construction, and cross-user isolation after logout.

Do RSC, streaming SSR, and PPR invalidate the four-way model?

They allow static and dynamic work to be combined more finely within one route, but do not remove the decision inputs. You still need to state where work runs, what initial HTML contains, how long data is cached, how much JavaScript the client receives, and how a dynamic region fails. In an interview, establish CSR/SSR/SSG/ISR delivery and freshness, then explain how RSC, streaming, or partial prerendering improves a specific region.

How do you prevent an invalidation storm?

Coalesce repeated events by entity, reject obsolete versions, add bounded regeneration concurrency and jitter, and allow one generator per cache key. Monitor queue depth, generation duration, failures, and content age. If backlog grows, preserve authoritative dynamic reads for price and inventory while the product body keeps serving its last successful version.

Public sources

Related questions