Build1 distinct publisher2 min readPublished
Streaming sends the sidebar and the skeleton before getSession() comes back, so a logged-out visitor sees the shape of a dashboard until the redirect lands. Closing that gap costs first-byte time on every protected route.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
Follow any of these and your For You feed starts watching them — no settings page required.
build
Next.js checks Origin for Server Actions. Move the same logic to a route handler and it stops.1 distinct publisher
build
Next.js 16 moves the cache decision into the component tree, and the review surface with it1 distinct publisher
build
Next.js 'use cache' claims 700ms TTFB down to 60ms. Every deploy hands the bill back1 distinct publisher
build
With CRA out of React's docs, the new project default is a rendering decision1 distinct publisher
An HTTP response goes out in a fixed order: status line, headers, then body. By the time the session lookup settles, the body has already started, so the correction cannot be a status code on that response; it has to be an instruction inside the stream that the client acts on [1]. That transport detail is an inference drawn from response ordering. What the post actually reports is the browser navigating away [6].
The useful consequence is that this comes down to latency. The width of the window is the interval between React's first flush and the moment getSession() resolves [2]. Whatever your p99 session lookup is, that is roughly how long the shell sits in front of someone who is not logged in [2].
Being precise about what escapes decides whether this is a bug or an incident. According to the author, what streams is structure: which sections exist, what the navigation looks like, and sometimes feature names meant to stay unannounced until launch [9]. The same post flags the case that degrades further, where the wrapped subtree holds nested pieces that do not share the auth dependency and can therefore resolve and flush on their own schedule [10].
Hoisting the await above the returned JSX is a structural requirement. React has nothing renderable to emit from that route until the promise settles, so the decision exists before any bytes do [12]. The author's rule follows from that: authorization sits outside and above any boundary that gates access, because a redirect issued after streaming starts only corrects the mistake after the fact, once the wrong content has already shipped [13]. The layout gets its own check because a layout renders before its children [14].
The bill arrives in two places. First, the route is now serialized on auth, and time to first byte includes the session lookup you were previously overlapping with render [4]. In my context that is the right trade, since spending first-byte budget to show a skeleton to a visitor who is about to be sent to /login is not a performance win. Second, doing it in the layout and again in the page puts two getSession() calls on one protected navigation [3]. The post does not discuss deduplication [3], so whether that is one query or two depends entirely on whether your session helper is memoized per request. Streaming is still the good part of the App Router [1]; it just means the ordering of your checks is now part of your threat model.
Ranked by verification strength, evidence, and original report placement.
In the Next.js App Router, streaming lets the browser start receiving and rendering parts of a page before every piece of data has finished loading.
Getting the interaction between auth checks and Suspense boundaries wrong does not throw an error; it occasionally shows a logged-out visitor a flash of something meant only for an authenticated user.
In the example app/dashboard/layout.tsx, the DashboardLayout renders a Sidebar that is not wrapped in Suspense.
In the example app/dashboard/page.tsx, DashboardPage wraps AuthenticatedContent in a Suspense boundary with a DashboardSkeleton fallback, and AuthenticatedContent awaits getSession() and calls redirect('/login') when there is no session.
Because Sidebar has no dependency on the auth check, React starts streaming it immediately along with the DashboardSkeleton fallback standing in for the still-loading AuthenticatedContent.
Only after getSession() resolves and comes back empty does redirect('/login') fire, at which point the browser navigates away.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 29, 2026
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Readable code, unmeasured effect
The mechanism is checkable without trusting anyone: both the broken and fixed page components are printed in full, and the ordering claim follows from what depends on the session and what does not. What is missing is everything quantitative and everything external — no timing of the window, no Next.js documentation cited on flush ordering, no reproduction beyond the author saying he watched it happen once on a slow connection during testing.
No usage signal
Nothing in this reporting tells us how common the pattern is in shipped code. There is no release, no telemetry, no repository survey, not even a reader account — the author's closing question asks whether anyone else has hit this, which is an admission that he does not know.
Headline sharper than the harm
A redirect that 'doesn't undo what already streamed' sounds like a breach, and the fix is presented as a rule for all gated routes. The author then does most of the deflating himself: no data streamed, and for most dashboards a flash of sidebar is not severe. What tips this slightly to overstated is that the residual claim — nested subtrees could leak something genuinely sensitive — is asserted rather than demonstrated, and the cost side of the prescribed fix goes unmentioned.
Advice with a storefront attached
The byline sells Next.js templates and the post signs off with the Gumroad link and an X handle, so authority on App Router subtleties is the product being advertised. The engagement ask — tell me in the comments whether this surprised you too — serves the same funnel. None of that makes the ordering claim wrong, but it does explain why the piece is framed as a discovery with a memorable rule rather than as a bounded caveat, and why no counter-argument is entertained.
Sound reasoning, single voice
We can be fairly confident about what the code does and much less confident about everything around it: one self-published author, no corroboration, no numbers, and no sense of how often this bites. The derived consequences we can stand behind — the duplicated session lookup and the first-byte cost — follow from his own samples, not from anything he measured.