When a meta-framework renders a page on the server, how does that render learn which user is signed in?
answer
- identity travels with the request
- the browser attached it, not the render
- cookie header in, session out
- no session is a normal branch
- request-scoped, never module-level
basics
~20 sThe incoming request carries a session cookie; server-side code reads it from the request headers, resolves it to a session or user, and feeds that into the render. Identity is a per-request input, never module-level state.
solid answer
~50 sA server render has no ambient notion of "the current user" — the same process may be rendering for several visitors at once. Identity has to come from something the request carried, and for a plain page navigation the browser attaches only cookies on its own, so the session cookie is the usual carrier. The render reads that cookie off the incoming request headers, verifies or looks it up to get a session, and branches: personalised view, signed-out view, or a redirect to sign-in. A missing, expired or tampered cookie all land in the same "no session" branch. The resolved value must stay scoped to that one request — parking it in a module-level variable hands one visitor's identity to the next request the process serves — and because the output now depends on the request, it is no longer one copy everybody can share.
go deeper
Remember the direction of travel: the browser sends the session cookie with the request, and the server render reads it from that request. Nothing about identity comes from the markup or from a global.
Be able to walk the read end to end — cookie header, verification or store lookup, session or nothing, then the branch — and explain why the resolved value has to be scoped to the single request.
Show that you have debugged the leak: a user seeing another user's name after a value was cached above request scope, and the concurrency or warm-instance reuse that produced it.
Frame it as a boundary decision: which surfaces are allowed to depend on per-request identity at all, since every one that does gives up being produced once and shared.
## Identity arrives with the request A server render produces HTML for exactly one request. There is no ambient "current user" the way there is in a desktop app that owns a session in memory: a long-running server may be rendering for dozens of visitors concurrently, and on a serverless function platform the same warm instance serves strangers back to back. **Anything the render knows about the visitor has to have travelled in on that request.** For a plain page navigation — a typed URL, a followed link, a reload — the browser attaches credentials on its own only in the form of cookies that match the origin and path. That is why a session cookie is the usual carrier for page renders. A request issued by script can also carry a bearer credential in an `Authorization` header, which is common for API-style calls, but the first HTML request for a route generally cannot. ## The shape of the read Whatever a given framework names the accessor, the sequence is the same: 1. Pull the named cookie's value out of the request's `Cookie` header. 2. Turn that value into a session — verify the integrity of a self-contained value, or look up an opaque identifier in whatever store holds sessions. 3. Get back either a session (typically a user identifier plus a few facts) or nothing. 4. Branch: render the personalised view, render the signed-out view, or redirect to the sign-in route. Step 3's "or nothing" is the case people forget. **A missing cookie, an expired session and a tampered value should all land in the same branch**, and that branch is a normal outcome, not an error path. ## Request scope is the whole discipline The resolved session belongs to one request and must not outlive it. Two ways teams break that: - **A module-level variable** holding "the current user", written on each read. On a long-running server two overlapping requests race and one render emits the other visitor's name; on a function platform the value simply survives into the next invocation. - **A client object created once at module scope and configured with the session** — the configuration sticks, so the next request reuses credentials that no longer belong to it. The safe shapes are: read it where you need it and let per-request deduplication collapse the repeats, or read it once at the edge of the request and carry it in a value the runtime scopes to that request. ## Server and client do not see the same thing | Vantage point | Can it see the session? | Why | |---|---|---| | Server render of a request | Yes | The cookie is on the request headers it was handed | | Script in the page | Not if the cookie is marked as unreadable by script | The browser withholds it from script while still sending it | | A build-time prerender | No | There is no request and no visitor at build time | | A shared cache in front of the app | It sees the header, but must not key on it by default | A stored personalised copy would be served to strangers | The build-time row is the one that surprises people: a route that is rendered ahead of time cannot personalise, because the visitor does not exist yet. Personalisation forces that route to be produced per request, or to leave a hole that is filled per request. ## What the read costs the response Once a render depends on the session: - Its HTML is about one person, so **no shared tier may store and replay it** for someone else. - The response usually needs cache directives that say so, and any cache that does store it must vary on the identity input rather than on the URL alone. - Work that does not depend on identity is worth keeping separate, so the personal part is the only part that has to be produced fresh. ## Common mistakes - Treating the absence of a cookie as an exception instead of the signed-out state. - Assuming script can read a session cookie the browser marks unreadable, then concluding the user is signed out when a network call proves otherwise. - Reading the session in a route that the build prerenders and wondering why every visitor sees the same name. - Caching the resolved user for "performance" in a scope wider than the request. - Deciding what to render from a value the client sent in the URL or a body field rather than from the verified session.
- What should the render do when the request carries no session cookie at all?Treat it as the signed-out state. The read simply returns nothing, and the route renders its public view or redirects to sign-in. An expired or tampered cookie should resolve to the same outcome, so there is one branch rather than three. Throwing on a missing cookie turns every logged-out visit into an error page.
- Can a route read identity from something other than a cookie?Yes. A request may carry a bearer credential in an `Authorization` header, which is typical when script does the fetching. For a plain page navigation the browser attaches only cookies by itself, so page renders almost always key on a cookie; header credentials show up on calls the page makes after it loads.
saying these in an interview costs you the question
- Thinks the server keeps a current-user global between requests
- Stores the resolved user in a module-level variable for speed
- Expects page script to read a cookie the browser hides from script
- Assumes a build-time prerender can see the visitor's session
- Treats a missing session cookie as an error rather than signed out
- Trusts a user id sent in the URL instead of the verified session