Next.js Discord

Discord Forum

Cold starts with SSG on the first page load on Vercel

Answered
Shikoku posted this in #help-forum
Open in Discord
ShikokuOP
Is there any way to get rid of cold starts in the context of SSG in the App Router? HTML files are generated and ready to go, so I don't understand why the server takes 2-3 seconds for the first page load. I don't want any dynamic behavior, just rendering the HTML file that has been built at built-time.

There is no such cold start in export mode. I tried adding dynamic = 'error' and dynamicParams = false, but I'm still hitting cold starts for all pages after every deployment on Vercel.

const SSGPage = ({ params }) => <div>SSG: {params.slug}</div>

export const generateStaticParams = () => Array.from({ length: 100 }, (_, i) => ({ slug: `${i}` }))

export const dynamic = 'error'
export const dynamicParams = false

export default SSGPage


This code is deployed here if you want to see what I am talking about:

https://minimal-gamma.vercel.app/1

Pick a number between 1 and 100 that hopefully no one has used before directly in the URL to see the 2-second load.
Answered by Shikoku
Thanks for your patience with this. I have now had confirmation from the team that the difference you're seeing in the time for the initial render when it's PRERENDER is currently expected behaviour. This is due to the way the initial request is fulfilled. For a fully static page, or using output: export to set a page as fully static when not using revalidate, the first response is served from the cache initially. When using the app or page router to render all pages at build time, even with no revalidation, the initial page is not served from the cache, but is added to the cache after the first response which is why subsequent requests to the page are faster.

In this case, the team is aware that this could be improved and they are working on that as part of their backlog tasks. However, I don't have a timeframe for when any improvements would be released but I have made them aware of your use case and need for this.
View full answer

100 Replies

@joulev And in the vercel log you can see whether a request had cold start or not, check there as well
ShikokuOP
On Vercel it says Cache : PRERENDER the 1st time you opened /69, then HIT
I am preparing a minimal repo
@Shikoku On Vercel it says Cache : PRERENDER the 1st time you opened /69, then HIT
That’s normal, if it was a cold start it would say “cold start duration”
Why is Vercel even creating these ISR functions just to serve plain HTML files?
@Shikoku Click to see attachment
This is interesting…
ShikokuOP
You might have had a fast page load because you are closer to IAD than me? I am in Asia. But it should come from the CDN, not a serverless function.
i'm also in asia
i just deployed your code. now we'll have to wait a while to guarantee cold boot, i will get back to you
@Shikoku Click to see attachment
so ISR here is normal, because the routes are not forever a plain file, they might be invalidated by revalidatePath so nextjs needs to prepare a serverless function that would rerun the route whenever the path is invalidated
but for cold start, wait maybe a couple of hours so we are definitely sure it is a cold start
@Shikoku Is there any way to disable this behavior?
not that i know of. it doesn't harm, why disable it?
ShikokuOP
I mean, maybe we are talking about different things with "cold starts". I am just referring to the fact that the serverless function is running, when I would expect it not to exist in the first place
@joulev not that i know of. it doesn't harm, why disable it?
ShikokuOP
it's making my websites very slow to navigate after every deployment, it is pretty bad
@Shikoku I mean, maybe we are talking about different things with "cold starts". I am just referring to the fact that the serverless function is running, when I would expect it not to exist in the first place
1. cold start in the serverless context (e.g. vercel) means this: if a lambda (serverless function) is not run after a while (15 minutes?), it is shut down, so the next request needs to wake it up, costing a few hundred milliseconds – that a few hundred milliseconds is called cold start
2. in this case, the routes are static. the serverless functions are not run. or at least, they shouldn't be run
ShikokuOP
You're right, I guess what I mean is "why is the request going through Vercel's cache"
When I switch to export mode, everything is instantaneous because it's coming straight from the CDN, but I lose some functionalities of Next's server
@Shikoku You're right, I guess what I mean is "why is the request going through Vercel's cache"
ah that's perfectly normal and intended. it's that cache that is storing the static page data, so obviously to get the page data the router needs to access the cache. see more info in [Full Route Cache](https://nextjs.org/docs/app/building-your-application/caching#full-route-cache)
but this cache should be very very fast?
thousands of nextjs apps have been using it for static generation and they all load very fast (my apps included)
ShikokuOP
Can you send me a link to your deployment of my repo?
@joulev thousands of nextjs apps have been using it for static generation and they all load very fast (my apps included)
this is from my personal app (joulev.dev). it is a cache HIT indeed, it does have a ISR function generated indeed, but the page still loads instantly
it's normal
@Shikoku Can you send me a link to your deployment of my repo?
we will need to wait maybe an hour to guarantee cold start. any visitors visiting it during that time will mean we have to restart the timer again
But you are getting slow first loads on https://vercel-app-ssg-cold-starts.vercel.app/ right?
And then it's faster on second load
hmm lemme record the screen for you, it's my first time loading it on my desktop too so there is no browser cache or anything
it does feel slow-ish hmm that's really weird
not disastrously slow but slower than i expected
ShikokuOP
It is not disastrously slow, but this is a very minimal page.
ok this is interesting. something's definitely wrong here but i can't say what it is
ShikokuOP
(sending the vietnamese version, that no one uses)
https://webgamer.io/vn
EDIT Nov 29 2023: the site has been converted to use export mode, which doesn't have slow page loads.
because no way your minimal SSG loads slower than my much more complex websites
ShikokuOP
click on any game, and you will see that it is painfully slow
that is true
that's super weird
ShikokuOP
I purposely disable <Link> prefetching on this website to reduce bandwidth. I suspect that this issue is not often noticed because <Link>'s prefetching makes everything feel instantaneous + it triggers that initial hit on the pages linked to
ok so here are the results from my deployed version of your code: it loads slowly too
this is crazy i have never seen anything like this
from the second load onward it is indeed fast
i think you should open a bug report here
this should be a bug
if you have vercel pro you should create a customer support case as well
ShikokuOP
Thanks, I will. Wanted to check with the community first to see if I was missing something obvious
yeah your code is fine
the build log also says it is static so it should load instantly
so seeing it loads this slowly does surprise me
@joulev https://debug-git-nextjs-cold-start-test-verekia-joulev.vercel.app/
in the vercel log, none of the requests is registered to have cold boot, but it does have a cold boot-like behaviour
@joulev in the vercel log, none of the requests is registered to have cold boot, but it does have a cold boot-like behaviour
ShikokuOP
Yeah, it seems like the initial build-time caching didn't register correctly, so it has to do it again, or something like that.
(thank you so much for having a look at this by the way)
I see the PRERENDER header though it sounds weird
I mean 800ms for that that's huge, it's 44ms after the render
you might want to open an issue on Vercel github (not Next.js cause this might be Vercel specific)
are you on the free offer maybe?
Vercel doesn't necesarily use the "normal" Next.js build system
it brings on more optimization
you might have answered above but did you log the renders?
What bothers me more is that you could have an API running only during a controlled build-time
this would make the render totally fail
while you configured your site to be totally static so you expect it to never rerender after the build for instance
feel free to keep us informed that's an interesting case
@Eric Burel are you on the free offer maybe?
ShikokuOP
I'm on the Pro tier. I will open a support ticket + open a GH issue. Yeah, I also think it might be a Vercel problem more than a Next.js one
@Eric Burel you might have answered above but did you log the renders?
ShikokuOP
Not sure what you mean by logging the renders?
@Shikoku Not sure what you mean by logging the renders?
Just a console.log when the static page render
You should have no log when opening a page
ShikokuOP
I just converted my App router app back to the Pages router, and I was surprised to see that even with the Pages router, ISR functions are created for all SSG pages. So it's not related to the App router.
I opened a support ticket and will follow up here.
Same issue
ShikokuOP
I now got rid of all my API routes to use Next.js in export mode, which has the intended behavior. Every page now loads instantly, no ISR caching behavior at all.
Had to create a separate repo for Vercel API routes, which is very inconvenient, but still better than 2s TTFB for all pages of my site
ShikokuOP
@Eric Burel @joulev After a month of updates on the vercel support ticket, I finally got the final answer that this is expected and could be improved in the future
ShikokuOP
Thanks for your patience with this. I have now had confirmation from the team that the difference you're seeing in the time for the initial render when it's PRERENDER is currently expected behaviour. This is due to the way the initial request is fulfilled. For a fully static page, or using output: export to set a page as fully static when not using revalidate, the first response is served from the cache initially. When using the app or page router to render all pages at build time, even with no revalidation, the initial page is not served from the cache, but is added to the cache after the first response which is why subsequent requests to the page are faster.

In this case, the team is aware that this could be improved and they are working on that as part of their backlog tasks. However, I don't have a timeframe for when any improvements would be released but I have made them aware of your use case and need for this.
Answer
ShikokuOP
So I have to stick to output: export 🫠
ShikokuOP
Yeah, I'm not sure what kind of cache it is either.
I am seeing cache "logs" but I'm not sure where I could see a console log for Prerender functions in Vercel's dashboard
What's clear is that it goes through a "PRERENDER" step for pages that have already been built at build-time
🤷‍♂️
This makes is essentially non-viable for my use-case. I have to stick to export mode
Plott Hound
out of curiosity which location did you chose for deployment? is it the default Washington DC?