Questions
31 of 33
1Explain server-side rendering (SSR) in Next.js.
2List the benefits of Server-Side Rendering in Next.js.
3What are server components?
4How to use server components in next js?
5What is the React Server Component Payload (RSC)?
6Describe how server components are rendered.
7Describe server rendering strategies
8How can you keep Server-only Code out of the Client Environment
9What are the issues of using context provider at the root of the application?
10List dynamic functions available to server components.
11List all Dynamic APIs.
12How do we opt for Static Rendering, Dynamic Rendering and Streaming?
13Explain the difference between SSR, SSG, ISR, and CSR in Next.js. When would you choose each?
14How does getServerSideProps work internally? What is its execution context?
15What are the performance trade-offs of SSR vs SSG in a high-traffic production app?
16How does Next.js handle hydration? What is a hydration mismatch, and how do you debug it?
17What happens when getServerSideProps throws an error? How do you handle it gracefully?
18How would you architect a Next.js app that needs both personalised (SSR) and cacheable (SSG) pages at scale?
19Explain the App Router vs Pages Router SSR model differences. How does React Server Components change the SSR paradigm?
20How do React Server Components (RSC) differ from traditional SSR? Can they be used together?
21How does streaming SSR work in Next.js 13+? What role does Suspense play?
22How would you implement partial hydration or Islands Architecture in Next.js?
23Explain how Next.js handles data fetching waterfall problems in SSR and how you'd mitigate them.
24How would you implement partial hydration or Islands Architecture in Next.js?
25How do you implement caching strategies for SSR responses in Next.js? (CDN, Cache-Control, stale-while-revalidate)
26How would you reduce TTFB (Time to First Byte) in an SSR-heavy Next.js app?
27What's the difference between fetch caching in the App Router vs traditional getServerSideProps?
28How do you avoid redundant database/API calls across multiple server components on the same page?
29How do you securely handle authentication in SSR? What are the risks of passing tokens via cookies vs headers?
30How do you prevent sensitive server-side data from leaking to the client bundle?
31How would you implement role-based rendering on the server without exposing protected routes to the client?
32How do you debug SSR-only issues that don't appear in local development?
33How can we control dynamic rendering behaviour in next js?
31 / 33

How would you implement role-based rendering on the server without exposing protected routes to the client?

Implement server-side role-based rendering using a multi-layered approach: middleware for early routing decisions, Server Components with role verification, and experimental forbidden() for 403 responses, while architecturally separating code by role to prevent client-side exposure

Implementing role-based rendering without exposing protected content requires shifting authorization completely to the server. The fundamental principle is that unauthorized users should never receive the JavaScript code or markup for protected routes. This is achieved through a defense-in-depth strategy: middleware provides fast edge-level filtering, Server Components perform database-backed permission checks, and architectural patterns ensure that admin-only code never reaches unauthorized clients. Critical vulnerabilities like CVE-2025-29927 (CVSS 9.1) have demonstrated that relying solely on middleware can be dangerous, making layered validation essential .

Core Security Principles
  1. 1

    Never rely on client-side checks: Client-side role checks provide zero security value—attackers can modify client JavaScript to bypass them entirely .

  2. 2

    Defense in depth: Implement authorization at multiple layers (middleware, Server Components, API routes) so that a bypass in one layer doesn't compromise security .

  3. 3

    Fail securely: Default to denying access and returning 404 for unauthorized requests to prevent information leakage about protected routes .

  4. 4

    Code separation: Architecturally separate code for different roles to prevent admin components from being included in user bundles .

Middleware provides the first line of defense, running at the edge before requests reach your pages. It can quickly validate JWTs and redirect unauthenticated users, but should not be the only protection. The CVE-2025-29927 vulnerability showed that attackers could bypass middleware entirely by manipulating headers, so middleware checks must be complemented by deeper validation . Use middleware for fast, coarse-grained routing decisions like redirecting logged-out users or rewriting requests based on basic role claims .

Middleware Role-Based Protection

The critical layer of protection happens in Server Components themselves. After middleware, the request reaches your page component where you must verify authorization again—this time with full database access. The Next.js documentation emphasizes that authorization should be enforced at the data access layer, where you can verify permissions against your database rather than just token claims . This prevents token tampering and ensures that revoked permissions are immediately enforced.

Server Component with Role Verification

Next.js 15.1 introduced an experimental forbidden() function that throws an error rendering a 403 page . This provides a semantic way to handle authorization failures. To use it, enable the authInterrupts flag in your config. The forbidden() function can be called in Server Components, Server Actions, and Route Handlers, and pairs with a custom forbidden.js file for branded error pages .

Using forbidden() for Authorization

The final and most critical layer is authorization at the data level. Even if a user bypasses page-level checks, they should never be able to access data they don't own. Create a dedicated Data Access Layer (DAL) that enforces permissions for every database query . This ensures that even if an attacker finds a way to call internal functions, authorization is still enforced.

Data Access Layer with Built-in Authorization

A critical but often overlooked aspect is preventing admin code from reaching client bundles. Even if you protect routes, if admin components are imported in shared layouts, their JavaScript may still be sent to users . The solution is architectural separation: keep admin pages in their own route group with separate layouts, and never import admin-only code in user-facing components. Use route groups like (admin) and (user) to create clear boundaries .

Route Structure for Code Separation
Handling Server Actions Securely
  1. 1

    Always revalidate authorization inside Server Actions: Even if the UI hides buttons, users can craft requests directly to actions .

  2. 2

    Use the 'use server' directive with role checks at the beginning of each action .

  3. 3

    Never trust client-provided data for authorization decisions—always check the session.

  4. 4

    Return generic errors to avoid leaking information about why authorization failed .

Secure Server Action with Role Check

A important security consideration is whether to return 404 (Not Found) or 403 (Forbidden) for unauthorized access. Returning 404 for protected routes provides better security through obscurity—attackers cannot distinguish between non-existent routes and protected ones . However, returning explicit 403 errors can be useful for debugging and providing clear user feedback. The experimental forbidden() function provides a semantic way to return 403 when you want explicit denial .

Implementation Checklist
  1. 1

    Use middleware for coarse-grained edge filtering but never as sole protection

  2. 2

    Verify authorization in every Server Component using database-backed sessions

  3. 3

    Create a Data Access Layer that enforces permissions on all queries

  4. 4

    Architecturally separate code for different roles to prevent bundle leakage

  5. 5

    Validate authorization in every Server Action

  6. 6

    Consider using forbidden() for explicit 403 responses

  7. 7

    Upgrade Next.js to patched versions (≥12.3.5, ≥13.5.9, ≥14.2.25, ≥15.2.3) to fix CVE-2025-29927