Ask
29

I thought these pages were static and they are rendering on every request: how do you tell, and what makes it flip?

A mostly content site. Pages come from a database at build time and I expected them to be prerendered and served as static.

What I am seeing instead is that every request hits the server and my database is getting far more traffic than it should. Response times are also worse than they were.

Somewhere along the way something made these routes dynamic, and I cannot work out what or when. I did not change the pages themselves.

How do I find out which routes are static and which are not, and what are the things that silently flip a route from one to the other? I would rather understand the rule than guess at it.

3 answers Share
Report

Answering anonymously, a moderator will review it first.

  • @cache_on_purpose · 3w ago

    The other half of your symptom is the database traffic, and that is caching rather than rendering. They are related and they are not the same question.

    A dynamic route can still be cheap if its data is cached. A static route with uncached fetches at build time is fine because it only builds once. What you have is the bad combination - dynamic rendering plus uncached data, so every request goes all the way through.

    So fix both, and fix them separately:

    Be explicit about caching on every data fetch rather than relying on whichever default your version has. Defaults here have changed between major versions and a lot of people acquired this problem during an upgrade without touching a line of their own code.

    Decide what each route actually needs. Content pages that change rarely want caching with revalidation on a sensible interval. Genuinely per-user pages should be dynamic and that is correct.

    Then re-check the build table and confirm the routes you expect to be static are.

    And on your response times: a route being dynamic is not automatically slow. It is slow when it is dynamic and doing uncached work. Fixing the caching often recovers most of the performance even if the route stays dynamic, which is worth knowing if some of them genuinely need to be.

    21
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report
  • @build_output_reader · 3w ago

    The answer is in the build output and almost nobody reads it.

    At the end of a build you get a table of every route with a symbol next to it saying how it will be rendered - static, dynamic, or rendered on demand. That table is authoritative. Before theorising about anything, run a build and look at which of your routes are marked dynamic. That converts the question from what might be happening into which routes and, from there, what they have in common.

    Once you know which routes, the causes are a short list. A route becomes dynamic if anything in it reads something that can only exist per request. In practice:

    • Reading cookies or headers, anywhere in the tree
    • Reading the request URL's search parameters
    • An uncached data fetch, depending on your version's defaults
    • Explicitly opting out with a route segment config, possibly set months ago and forgotten
    • Draft or preview mode being checked

    The critical part, and the one that catches everybody: it is inherited upwards through the tree. A layout that reads cookies makes every page beneath it dynamic. So the route showing the symptom is often not the file that caused it.

    Start at the layouts, not the pages.

    30
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report
  • @one_import_dynamic · 3w ago

    Following that: the thing that got me was an import, not a call.

    We had a small helper that read a cookie to work out the current user. Somebody imported it into a shared component for an unrelated reason: it exposed a formatting function that happened to live in the same file. The cookie code was never called on those pages. It did not matter; the route was dynamic from then on.

    That is why you cannot find when it changed by looking at the pages. The change is a line in a file you were not thinking about.

    How to hunt it:

    Search for the request-scoped imports across the tree, cookies, headers, anything auth-related: and see which components pull them in, directly or transitively.

    Bisect if the search is too broad. Comment out half the imports in the suspect layout, build, look at the table. Three or four rounds and you have it.

    Split the file once you find it. Formatting helpers and request-scoped helpers should not live together, and this is exactly why.

    The wider habit worth taking from it: treat the build output table as something you look at, the way you would look at a bundle size. A route quietly moving from static to dynamic is a real regression with a real cost, and nothing else warns you about it.

    26
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report