skip to content

In a meta-framework that prerenders routes at build time, which inputs make a route's output request-dependent?

level: juniorimportance: must knowfreq 72%

answer

  1. could two visitors get different bytes?
  2. only what arrives with the request counts
  3. cookies, headers, query string, caller address
  4. a content query is not request-bound
  5. derived values inherit request-boundness

basics

~20 s

Input that arrives with the HTTP request and differs between callers: the cookie jar, request headers, the query string, the caller's address. Reading a database, a config value or a path parameter does not, by itself.

solid answer

~50 s

A route is static when one rendered output can serve every visitor, so the HTML can be produced before any request exists. It becomes dynamic when the render reads something only the request carries: cookies, request headers such as `Authorization` or `Accept-Language`, the query string, or the caller's network address. Anything derived from those is request-bound too — a database row looked up by the session id in a cookie is a per-request read even though the database is not. What does *not* count is data that is the same for everyone at the moment of the render: a content query, an environment variable, a path parameter whose value is part of the URL. The working test is simple: could two visitors asking for the same URL legitimately receive different bytes? If yes, the route is dynamic.

go deeper

for a junior

Learn the one-line test: if two visitors at the same URL could get different bytes, the route is dynamic. Memorise the four request-bound sources — cookies, headers, query string, caller address.

for a middle

Be able to explain why a database read is not request-bound but a lookup keyed by a session cookie is, and why one read in a shared layout can taint every route that uses it.

for a senior

Show that you check the whole render tree, not the page file, and that you treat freshness as a regeneration question rather than a reason to go per-request.

for a principal

Frame it as a cost boundary: each route that crosses into per-request rendering moves work from build to runtime and gives up shared caching, so the classification belongs in review, not in the hosting bill.

## Static and dynamic are a promise about the request A route is **static** when a single rendered output can serve every visitor: the HTML can be produced before any request exists — at build time, or once and then reused — and handed out unchanged. A route is **dynamic** when the framework has to run the render for each request, because the output depends on something only that request carries. The whole classification turns on one test: > Could two visitors asking for the **same URL** legitimately receive **different bytes**? If yes, the route is dynamic. If no, its output can be produced ahead of time, stored, and served from a shared cache or even a plain static file host. ## What counts as request-bound input Request-bound input is state that arrives *with* the HTTP request and can differ between callers: - **The cookie jar** — a session cookie, a theme preference, a consent flag, a draft-preview flag. - **Request headers** — `Authorization`, `Accept-Language`, `User-Agent`, client-hint headers, or a header a proxy or CDN injected such as a country code. - **The query string** — `?page=2`, `?sort=price`. The path identifies the document; the query is normally treated as per-request state. - **The caller's address** — the client IP, or whatever the proxy chain reports as it. - **The request method and body** — a render that responds to a submitted form rather than a plain navigation. Anything **derived** from those is request-bound by transitivity. A database row fetched by the user id inside a session cookie is a per-request read: the query is fixed, but the key came from the request, so two visitors get different rows. ## What looks request-bound but is not | Input the render reads | Request-bound? | Why | |---|---|---| | Cookie, header, query string, client IP | Yes | Differs per caller, arrives on the request | | Row keyed by a value taken from a cookie | Yes | The key came from the request | | Content query with a fixed key | No | Same answer for everyone at render time | | Environment variable or build configuration | No | Fixed for the whole deployment | | A path parameter such as a product slug | No | Part of the URL, so it can be prerendered per value | | The clock, or a random number | No | Varies, but not *with the request* — it freezes into whatever copy was produced | The last row is the one that surprises people. Reading the current time does make the output vary over time, but it is not request state, so a prerendering framework will happily freeze the build-time timestamp into the HTML and serve it for a month. Freshness is a caching and regeneration problem, not a static-versus-dynamic one. ## Why one read decides the whole route A route's output is normally rendered as one unit: the page, the layouts wrapped around it, and every module they pull in. That means a single request-bound read **anywhere in what the route renders** taints the whole output, including a read in a shared layout that a hundred unrelated routes also use. This is why a small change — greeting the signed-in user in a shared header — can move a whole site off prerendering at once. Some frameworks let a single route mix both: a prerendered shell with per-request holes, which changes that granularity. Treat whole-route tainting as the default and check what your own framework offers. ## What actually changes when a route is dynamic Once a route is per-request, there is no build-time copy to serve, and no shared cache hit unless you deliberately add response caching headers; every view costs a render on the server. That is the reason interviewers ask this at screening level: the classification is not a label in a build log, it is the difference between serving a file and running code for every visitor. ## How to reason about a route in practice 1. List everything the render reads, including reads inside shared layouts and shared modules. 2. For each read, ask whether its value could differ for two visitors hitting the same URL at the same instant. 3. If none can, the route can be static; freshness is then handled by rebuilding or regenerating, not by rendering per request. 4. If one can, decide whether you actually need it in the server-rendered HTML — moving it to a browser-side fetch is the usual way to keep the route static.

  • Does reading the current time during render make a route request-dependent?
    No. The clock is not carried on the request, so a prerendering framework treats the render as static and freezes the timestamp into the stored HTML — which is usually the bug people actually hit. Keeping a time-sensitive page fresh is a job for rebuilding, regeneration, or rendering the timestamp in the browser, not for marking the route dynamic.
  • A route queries a database on every render. Is it dynamic?
    Not on that basis alone. If the query key is fixed, every visitor gets the same answer at render time, so the result can be baked into a prerendered page and refreshed by rebuilding or regenerating. It becomes dynamic only when the key comes from the request — a session cookie, a query-string filter, a caller-specific header.
  • Is the query string really request state when it is part of the URL?
    Most frameworks treat it that way: the path enumerates documents to prerender, while the query expresses per-visitor intent such as sorting or pagination, and prerendering every combination is impractical. So a render that reads the query string usually flips the route to per-request, which is why filters are often applied in the browser instead.

A prerendered route is a printed newspaper: one run, everybody gets the same copy. A dynamic route is a till receipt — it cannot be printed until someone walks up, because half of it is about them.

saying these in an interview costs you the question

  • Thinks any route that fetches data at render time must be dynamic.
  • Calls a route dynamic because its path contains a parameter.
  • Believes reading an environment variable makes a route request-dependent.
  • Assumes fresh data can only come from per-request rendering.
  • Thinks reading the clock counts as request-bound input.
  • Ignores request-bound reads hidden in a shared layout.